• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

javadev / underscore-java / #4211

04 Jun 2025 06:13PM CUT coverage: 100.0%. Remained the same
#4211

push

web-flow
Spring boot 3.5.0

4519 of 4519 relevant lines covered (100.0%)

1.0 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

100.0
/src/main/java/com/github/underscore/U.java
1
/*
2
 * The MIT License (MIT)
3
 *
4
 * Copyright 2015-2025 Valentyn Kolesnikov
5
 *
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
package com.github.underscore;
25

26
import java.io.FileInputStream;
27
import java.io.FileOutputStream;
28
import java.io.IOException;
29
import java.io.InputStream;
30
import java.io.OutputStream;
31
import java.net.URI;
32
import java.net.URISyntaxException;
33
import java.net.URL;
34
import java.nio.channels.Channels;
35
import java.nio.channels.ReadableByteChannel;
36
import java.nio.charset.StandardCharsets;
37
import java.nio.file.Files;
38
import java.nio.file.Path;
39
import java.nio.file.Paths;
40
import java.util.ArrayList;
41
import java.util.Arrays;
42
import java.util.Collection;
43
import java.util.Collections;
44
import java.util.Comparator;
45
import java.util.Enumeration;
46
import java.util.HashMap;
47
import java.util.HashSet;
48
import java.util.Iterator;
49
import java.util.LinkedHashMap;
50
import java.util.List;
51
import java.util.Locale;
52
import java.util.Map;
53
import java.util.Optional;
54
import java.util.Properties;
55
import java.util.Set;
56
import java.util.function.BiConsumer;
57
import java.util.function.BiFunction;
58
import java.util.function.BinaryOperator;
59
import java.util.function.Consumer;
60
import java.util.function.Function;
61
import java.util.function.Predicate;
62
import java.util.zip.GZIPInputStream;
63
import javax.xml.xpath.XPath;
64
import javax.xml.xpath.XPathConstants;
65
import javax.xml.xpath.XPathFactory;
66
import org.w3c.dom.NodeList;
67

68
@SuppressWarnings({
69
    "java:S135",
70
    "java:S1168",
71
    "java:S3655",
72
    "java:S3740",
73
    "java:S3776",
74
    "java:S4423",
75
    "java:S4830",
76
    "java:S5843",
77
    "java:S5996",
78
    "java:S5998"
79
})
80
public class U<T> extends Underscore<T> {
81
    private static final int DEFAULT_TRUNC_LENGTH = 30;
82
    private static final String DEFAULT_TRUNC_OMISSION = "...";
83
    private static final java.util.regex.Pattern RE_LATIN_1 =
1✔
84
            java.util.regex.Pattern.compile("[\\xc0-\\xd6\\xd8-\\xde\\xdf-\\xf6\\xf8-\\xff]");
1✔
85
    private static final java.util.regex.Pattern RE_PROP_NAME =
1✔
86
            java.util.regex.Pattern.compile(
1✔
87
                    "[^.\\[\\]]+|\\[(?:(-?\\d+(?:\\.\\d+)?)|([\"'])((?:(?!\2)\\[^\\]|\\.)*?)\2)\\]|"
88
                            + "(?=(\\.|\\[\\])(?:\4|$))");
89
    private static final Map<String, String> DEBURRED_LETTERS = new LinkedHashMap<>();
1✔
90
    private static final Map<String, List<String>> DEFAULT_HEADER_FIELDS = new HashMap<>();
1✔
91
    private static final Set<String> SUPPORTED_HTTP_METHODS =
1✔
92
            new HashSet<>(Arrays.asList("GET", "POST", "PUT", "DELETE"));
1✔
93
    private static final int BUFFER_LENGTH_1024 = 1024;
94
    private static final int RESPONSE_CODE_400 = 400;
95
    private static final String ROOT = "root";
96
    private static final String UPPER = "[A-Z\\xc0-\\xd6\\xd8-\\xde\\u0400-\\u04FF]";
97
    private static final String LOWER = "[a-z\\xdf-\\xf6\\xf8-\\xff]+";
98
    private static final String SELF_CLOSING = "-self-closing";
99
    private static final String NIL_KEY = "-nil";
100
    private static final String OMIT_XML_DECL = "#omit-xml-declaration";
101
    private static final String YES = "yes";
102
    private static final java.util.regex.Pattern RE_WORDS =
1✔
103
            java.util.regex.Pattern.compile(
1✔
104
                    UPPER + "+(?=" + UPPER + LOWER + ")|" + UPPER + "?" + LOWER + "|" + UPPER
105
                            + "+|\\d+");
106
    private static final String ENCODING = "#encoding";
107

108
    static {
109
        String[] deburredLetters =
1✔
110
                new String[] {
111
                    "\u00c0", "A", "\u00c1", "A", "\u00c2", "A", "\u00c3", "A", "\u00c4", "A",
112
                    "\u00c5", "A", "\u00e0", "a", "\u00e1", "a", "\u00e2", "a", "\u00e3", "a",
113
                    "\u00e4", "a", "\u00e5", "a", "\u00c7", "C", "\u00e7", "c", "\u00d0", "D",
114
                    "\u00f0", "d", "\u00c8", "E", "\u00c9", "E", "\u00ca", "E", "\u00cb", "E",
115
                    "\u00e8", "e", "\u00e9", "e", "\u00ea", "e", "\u00eb", "e", "\u00cC", "I",
116
                    "\u00cd", "I", "\u00ce", "I", "\u00cf", "I", "\u00eC", "i", "\u00ed", "i",
117
                    "\u00ee", "i", "\u00ef", "i", "\u00d1", "N", "\u00f1", "n", "\u00d2", "O",
118
                    "\u00d3", "O", "\u00d4", "O", "\u00d5", "O", "\u00d6", "O", "\u00d8", "O",
119
                    "\u00f2", "o", "\u00f3", "o", "\u00f4", "o", "\u00f5", "o", "\u00f6", "o",
120
                    "\u00f8", "o", "\u00d9", "U", "\u00da", "U", "\u00db", "U", "\u00dc", "U",
121
                    "\u00f9", "u", "\u00fa", "u", "\u00fb", "u", "\u00fc", "u", "\u00dd", "Y",
122
                    "\u00fd", "y", "\u00ff", "y", "\u00c6", "Ae", "\u00e6", "ae", "\u00de", "Th",
123
                    "\u00fe", "th", "\u00df", "ss"
124
                };
125
        for (int index = 0; index < deburredLetters.length; index += 2) {
1✔
126
            DEBURRED_LETTERS.put(deburredLetters[index], deburredLetters[index + 1]);
1✔
127
        }
128
        DEFAULT_HEADER_FIELDS.put(
1✔
129
                "Content-Type", Arrays.asList("application/json", "charset=utf-8"));
1✔
130
    }
1✔
131

132
    public enum XmlToJsonMode {
1✔
133
        REPLACE_SELF_CLOSING_WITH_NULL,
1✔
134
        REPLACE_SELF_CLOSING_WITH_STRING,
1✔
135
        REPLACE_EMPTY_VALUE_WITH_NULL,
1✔
136
        REPLACE_EMPTY_TAG_WITH_NULL,
1✔
137
        REPLACE_EMPTY_TAG_WITH_STRING,
1✔
138
        REMOVE_FIRST_LEVEL,
1✔
139
        WITHOUT_NAMESPACES,
1✔
140
        REPLACE_MINUS_WITH_AT,
1✔
141
        REPLACE_EMPTY_TAG_WITH_NULL_AND_MINUS_WITH_AT
1✔
142
    }
143

144
    public enum JsonToXmlMode {
1✔
145
        FORCE_ATTRIBUTE_USAGE,
1✔
146
        DEFINE_ROOT_NAME,
1✔
147
        REPLACE_NULL_WITH_EMPTY_VALUE,
1✔
148
        REPLACE_EMPTY_STRING_WITH_EMPTY_VALUE,
1✔
149
        ADD_ROOT,
1✔
150
        REMOVE_ARRAY_ATTRIBUTE,
1✔
151
        REMOVE_ATTRIBUTES
1✔
152
    }
153

154
    public U(final Iterable<T> iterable) {
155
        super(iterable);
1✔
156
    }
1✔
157

158
    public U(final String string) {
159
        super(string);
1✔
160
    }
1✔
161

162
    public static class Chain<T> extends Underscore.Chain<T> {
163
        public Chain(final T item) {
164
            super(item);
1✔
165
        }
1✔
166

167
        public Chain(final List<T> list) {
168
            super(list);
1✔
169
        }
1✔
170

171
        public Chain(final Map<String, Object> map) {
172
            super(map);
1✔
173
        }
1✔
174

175
        @Override
176
        public Chain<T> first() {
177
            return new Chain<>(Underscore.first(value()));
1✔
178
        }
179

180
        @Override
181
        public Chain<T> first(int n) {
182
            return new Chain<>(Underscore.first(value(), n));
1✔
183
        }
184

185
        @Override
186
        public Chain<T> firstOrNull() {
187
            return new Chain<>(Underscore.firstOrNull(value()));
1✔
188
        }
189

190
        @Override
191
        public Chain<T> firstOrNull(final Predicate<T> pred) {
192
            return new Chain<>(Underscore.firstOrNull(value(), pred));
1✔
193
        }
194

195
        @Override
196
        public Chain<T> initial() {
197
            return new Chain<>(Underscore.initial(value()));
1✔
198
        }
199

200
        @Override
201
        public Chain<T> initial(int n) {
202
            return new Chain<>(Underscore.initial(value(), n));
1✔
203
        }
204

205
        @Override
206
        public Chain<T> last() {
207
            return new Chain<>(Underscore.last(value()));
1✔
208
        }
209

210
        @Override
211
        public Chain<T> last(int n) {
212
            return new Chain<>(Underscore.last(value(), n));
1✔
213
        }
214

215
        @Override
216
        public Chain<T> lastOrNull() {
217
            return new Chain<>(Underscore.lastOrNull(value()));
1✔
218
        }
219

220
        @Override
221
        public Chain<T> lastOrNull(final Predicate<T> pred) {
222
            return new Chain<>(Underscore.lastOrNull(value(), pred));
1✔
223
        }
224

225
        @Override
226
        public Chain<T> rest() {
227
            return new Chain<>(Underscore.rest(value()));
1✔
228
        }
229

230
        @Override
231
        public Chain<T> rest(int n) {
232
            return new Chain<>(Underscore.rest(value(), n));
1✔
233
        }
234

235
        @Override
236
        public Chain<T> compact() {
237
            return new Chain<>(Underscore.compact(value()));
1✔
238
        }
239

240
        @Override
241
        public Chain<T> compact(final T falsyValue) {
242
            return new Chain<>(Underscore.compactList(value(), falsyValue));
1✔
243
        }
244

245
        @Override
246
        public Chain flatten() {
247
            return new Chain<>(Underscore.flatten(value()));
1✔
248
        }
249

250
        @Override
251
        public <F> Chain<F> map(final Function<? super T, F> func) {
252
            return new Chain<>(Underscore.map(value(), func));
1✔
253
        }
254

255
        @Override
256
        public <F> Chain<F> mapMulti(final BiConsumer<? super T, ? super Consumer<F>> mapper) {
257
            return new Chain<>(Underscore.mapMulti(value(), mapper));
1✔
258
        }
259

260
        @Override
261
        public <F> Chain<F> mapIndexed(final BiFunction<Integer, ? super T, F> func) {
262
            return new Chain<>(Underscore.mapIndexed(value(), func));
1✔
263
        }
264

265
        @Override
266
        public Chain<T> filter(final Predicate<T> pred) {
267
            return new Chain<>(Underscore.filter(value(), pred));
1✔
268
        }
269

270
        @Override
271
        public Chain<T> filterIndexed(final PredicateIndexed<T> pred) {
272
            return new Chain<>(Underscore.filterIndexed(value(), pred));
1✔
273
        }
274

275
        @Override
276
        public Chain<T> rejectIndexed(final PredicateIndexed<T> pred) {
277
            return new Chain<>(Underscore.rejectIndexed(value(), pred));
1✔
278
        }
279

280
        @Override
281
        public Chain<T> reject(final Predicate<T> pred) {
282
            return new Chain<>(Underscore.reject(value(), pred));
1✔
283
        }
284

285
        @Override
286
        public Chain<T> filterFalse(final Predicate<T> pred) {
287
            return new Chain<>(Underscore.filterFalse(value(), pred));
1✔
288
        }
289

290
        @Override
291
        public <F> Chain<F> reduce(final BiFunction<F, T, F> func, final F zeroElem) {
292
            return new Chain<>(Underscore.reduce(value(), func, zeroElem));
1✔
293
        }
294

295
        @Override
296
        public Chain<Optional<T>> reduce(final BinaryOperator<T> func) {
297
            return new Chain<>(Underscore.reduce(value(), func));
1✔
298
        }
299

300
        @Override
301
        public <F> Chain<F> reduceRight(final BiFunction<F, T, F> func, final F zeroElem) {
302
            return new Chain<>(Underscore.reduceRight(value(), func, zeroElem));
1✔
303
        }
304

305
        @Override
306
        public Chain<Optional<T>> reduceRight(final BinaryOperator<T> func) {
307
            return new Chain<>(Underscore.reduceRight(value(), func));
1✔
308
        }
309

310
        @Override
311
        public Chain<Optional<T>> find(final Predicate<T> pred) {
312
            return new Chain<>(Underscore.find(value(), pred));
1✔
313
        }
314

315
        @Override
316
        public Chain<Optional<T>> findLast(final Predicate<T> pred) {
317
            return new Chain<>(Underscore.findLast(value(), pred));
1✔
318
        }
319

320
        @Override
321
        @SuppressWarnings("unchecked")
322
        public Chain<Comparable> max() {
323
            return new Chain<>(Underscore.max((Collection) value()));
1✔
324
        }
325

326
        @Override
327
        public <F extends Comparable<? super F>> Chain<T> max(final Function<T, F> func) {
328
            return new Chain<>(Underscore.max(value(), func));
1✔
329
        }
330

331
        @Override
332
        @SuppressWarnings("unchecked")
333
        public Chain<Comparable> min() {
334
            return new Chain<>(Underscore.min((Collection) value()));
1✔
335
        }
336

337
        @Override
338
        public <F extends Comparable<? super F>> Chain<T> min(final Function<T, F> func) {
339
            return new Chain<>(Underscore.min(value(), func));
1✔
340
        }
341

342
        @Override
343
        @SuppressWarnings("unchecked")
344
        public Chain<Comparable> sort() {
345
            return new Chain<>(Underscore.sort((List<Comparable>) value()));
1✔
346
        }
347

348
        @Override
349
        @SuppressWarnings("unchecked")
350
        public <F extends Comparable<? super F>> Chain<F> sortWith(final Comparator<F> comparator) {
351
            return new Chain<>(Underscore.sortWith((List<F>) value(), comparator));
1✔
352
        }
353

354
        @Override
355
        public <F extends Comparable<? super F>> Chain<T> sortBy(final Function<T, F> func) {
356
            return new Chain<>(Underscore.sortBy(value(), func));
1✔
357
        }
358

359
        @Override
360
        @SuppressWarnings("unchecked")
361
        public <K> Chain<Map<K, Comparable>> sortBy(final K key) {
362
            return new Chain<>(Underscore.sortBy((List<Map<K, Comparable>>) value(), key));
1✔
363
        }
364

365
        @Override
366
        public <F> Chain<Map<F, List<T>>> groupBy(final Function<T, F> func) {
367
            return new Chain<>(Underscore.groupBy(value(), func));
1✔
368
        }
369

370
        @Override
371
        public <F> Chain<Map<F, T>> associateBy(final Function<T, F> func) {
372
            return new Chain<>(Underscore.associateBy(value(), func));
1✔
373
        }
374

375
        @Override
376
        public <F> Chain<Map<F, Optional<T>>> groupBy(
377
                final Function<T, F> func, final BinaryOperator<T> binaryOperator) {
378
            return new Chain<>(Underscore.groupBy(value(), func, binaryOperator));
1✔
379
        }
380

381
        @Override
382
        public Chain<Map<Object, List<T>>> indexBy(final String property) {
383
            return new Chain<>(Underscore.indexBy(value(), property));
1✔
384
        }
385

386
        @Override
387
        public <F> Chain<Map<F, Integer>> countBy(final Function<T, F> func) {
388
            return new Chain<>(Underscore.countBy(value(), func));
1✔
389
        }
390

391
        @Override
392
        public Chain<Map<T, Integer>> countBy() {
393
            return new Chain<>(Underscore.countBy(value()));
1✔
394
        }
395

396
        @Override
397
        public Chain<T> shuffle() {
398
            return new Chain<>(Underscore.shuffle(value()));
1✔
399
        }
400

401
        @Override
402
        public Chain<T> sample() {
403
            return new Chain<>(Underscore.sample(value()));
1✔
404
        }
405

406
        @Override
407
        public Chain<T> sample(final int howMany) {
408
            return new Chain<>(newArrayList(Underscore.sample(value(), howMany)));
1✔
409
        }
410

411
        @Override
412
        public Chain<T> tap(final Consumer<T> func) {
413
            Underscore.tap(value(), func);
1✔
414
            return new Chain<>(value());
1✔
415
        }
416

417
        @Override
418
        public Chain<T> forEach(final Consumer<T> func) {
419
            Underscore.forEach(value(), func);
1✔
420
            return new Chain<>(value());
1✔
421
        }
422

423
        @Override
424
        public Chain<T> forEachRight(final Consumer<T> func) {
425
            Underscore.forEachRight(value(), func);
1✔
426
            return new Chain<>(value());
1✔
427
        }
428

429
        @Override
430
        public Chain<Boolean> every(final Predicate<T> pred) {
431
            return new Chain<>(Underscore.every(value(), pred));
1✔
432
        }
433

434
        @Override
435
        public Chain<Boolean> some(final Predicate<T> pred) {
436
            return new Chain<>(Underscore.some(value(), pred));
1✔
437
        }
438

439
        @Override
440
        public Chain<Integer> count(final Predicate<T> pred) {
441
            return new Chain<>(Underscore.count(value(), pred));
1✔
442
        }
443

444
        @Override
445
        public Chain<Boolean> contains(final T elem) {
446
            return new Chain<>(Underscore.contains(value(), elem));
1✔
447
        }
448

449
        @Override
450
        public Chain<Boolean> containsWith(final T elem) {
451
            return new Chain<>(Underscore.containsWith(value(), elem));
1✔
452
        }
453

454
        @Override
455
        public Chain<T> invoke(final String methodName, final List<Object> args) {
456
            return new Chain<>(Underscore.invoke(value(), methodName, args));
1✔
457
        }
458

459
        @Override
460
        public Chain<T> invoke(final String methodName) {
461
            return new Chain<>(Underscore.invoke(value(), methodName));
1✔
462
        }
463

464
        @Override
465
        public Chain<Object> pluck(final String propertyName) {
466
            return new Chain<>(Underscore.pluck(value(), propertyName));
1✔
467
        }
468

469
        @Override
470
        public <E> Chain<T> where(final List<Map.Entry<String, E>> properties) {
471
            return new Chain<>(Underscore.where(value(), properties));
1✔
472
        }
473

474
        @Override
475
        public <E> Chain<Optional<T>> findWhere(final List<Map.Entry<String, E>> properties) {
476
            return new Chain<>(Underscore.findWhere(value(), properties));
1✔
477
        }
478

479
        @Override
480
        public Chain<T> uniq() {
481
            return new Chain<>(Underscore.uniq(value()));
1✔
482
        }
483

484
        @Override
485
        public <F> Chain<T> uniq(final Function<T, F> func) {
486
            return new Chain<>(newArrayList(Underscore.uniq(value(), func)));
1✔
487
        }
488

489
        @Override
490
        public Chain<T> distinct() {
491
            return new Chain<>(Underscore.uniq(value()));
1✔
492
        }
493

494
        @Override
495
        @SuppressWarnings("unchecked")
496
        public <F> Chain<F> distinctBy(final Function<T, F> func) {
497
            return new Chain<>(newArrayList((Iterable<F>) Underscore.uniq(value(), func)));
1✔
498
        }
499

500
        @Override
501
        @SuppressWarnings("unchecked")
502
        public Chain<T> union(final List<T>... lists) {
503
            return new Chain<>(Underscore.union(value(), lists));
1✔
504
        }
505

506
        @Override
507
        @SuppressWarnings("unchecked")
508
        public Chain<T> intersection(final List<T>... lists) {
509
            return new Chain<>(Underscore.intersection(value(), lists));
1✔
510
        }
511

512
        @Override
513
        @SuppressWarnings("unchecked")
514
        public Chain<T> difference(final List<T>... lists) {
515
            return new Chain<>(Underscore.difference(value(), lists));
1✔
516
        }
517

518
        @Override
519
        public Chain<Integer> range(final int stop) {
520
            return new Chain<>(Underscore.range(stop));
1✔
521
        }
522

523
        @Override
524
        public Chain<Integer> range(final int start, final int stop) {
525
            return new Chain<>(Underscore.range(start, stop));
1✔
526
        }
527

528
        @Override
529
        public Chain<Integer> range(final int start, final int stop, final int step) {
530
            return new Chain<>(Underscore.range(start, stop, step));
1✔
531
        }
532

533
        @Override
534
        public Chain<List<T>> chunk(final int size) {
535
            return new Chain<>(Underscore.chunk(value(), size, size));
1✔
536
        }
537

538
        @Override
539
        public Chain<List<T>> chunk(final int size, final int step) {
540
            return new Chain<>(Underscore.chunk(value(), size, step));
1✔
541
        }
542

543
        @Override
544
        public Chain<List<T>> chunkFill(final int size, final T fillValue) {
545
            return new Chain<>(Underscore.chunkFill(value(), size, size, fillValue));
1✔
546
        }
547

548
        @Override
549
        public Chain<List<T>> chunkFill(final int size, final int step, final T fillValue) {
550
            return new Chain<>(Underscore.chunkFill(value(), size, step, fillValue));
1✔
551
        }
552

553
        @Override
554
        public Chain<T> cycle(final int times) {
555
            return new Chain<>(Underscore.cycle(value(), times));
1✔
556
        }
557

558
        @Override
559
        public Chain<T> interpose(final T element) {
560
            return new Chain<>(Underscore.interpose(value(), element));
1✔
561
        }
562

563
        @Override
564
        public Chain<T> interposeByList(final Iterable<T> interIter) {
565
            return new Chain<>(Underscore.interposeByList(value(), interIter));
1✔
566
        }
567

568
        @Override
569
        @SuppressWarnings("unchecked")
570
        public Chain<T> concat(final List<T>... lists) {
571
            return new Chain<>(Underscore.concat(value(), lists));
1✔
572
        }
573

574
        @Override
575
        public Chain<T> slice(final int start) {
576
            return new Chain<>(Underscore.slice(value(), start));
1✔
577
        }
578

579
        @Override
580
        public Chain<T> slice(final int start, final int end) {
581
            return new Chain<>(Underscore.slice(value(), start, end));
1✔
582
        }
583

584
        public Chain<Map<String, Object>> set(final String path, Object value) {
585
            U.set(map(), path, value);
1✔
586
            return new Chain<>(map());
1✔
587
        }
588

589
        public Chain<Map<String, Object>> set(final List<String> paths, Object value) {
590
            U.set(map(), paths, value);
1✔
591
            return new Chain<>(map());
1✔
592
        }
593

594
        @Override
595
        public Chain<T> reverse() {
596
            return new Chain<>(Underscore.reverse(value()));
1✔
597
        }
598

599
        @Override
600
        public Chain<String> join() {
601
            return new Chain<>(Underscore.join(value()));
1✔
602
        }
603

604
        @Override
605
        public Chain<String> join(final String separator) {
606
            return new Chain<>(Underscore.join(value(), separator));
1✔
607
        }
608

609
        @Override
610
        public Chain<T> skip(final int numberToSkip) {
611
            return new Chain<>(value().subList(numberToSkip, value().size()));
1✔
612
        }
613

614
        @Override
615
        public Chain<T> limit(final int size) {
616
            return new Chain<>(value().subList(0, size));
1✔
617
        }
618

619
        @Override
620
        @SuppressWarnings("unchecked")
621
        public <K, V> Chain<Map<K, V>> toMap() {
622
            return new Chain<>(Underscore.toMap((Iterable<Map.Entry<K, V>>) value()));
1✔
623
        }
624

625
        public Chain<T> drop() {
626
            return new Chain<>(Underscore.drop(value()));
1✔
627
        }
628

629
        public Chain<T> drop(final Integer n) {
630
            return new Chain<>(Underscore.drop(value(), n));
1✔
631
        }
632

633
        public Chain<T> dropRight() {
634
            return new Chain<>(U.dropRight(value()));
1✔
635
        }
636

637
        public Chain<T> dropRight(final Integer n) {
638
            return new Chain<>(U.dropRight(value(), n));
1✔
639
        }
640

641
        public Chain<T> dropWhile(final Predicate<T> pred) {
642
            return new Chain<>(U.dropWhile(value(), pred));
1✔
643
        }
644

645
        public Chain<T> dropRightWhile(final Predicate<T> pred) {
646
            return new Chain<>(U.dropRightWhile(value(), pred));
1✔
647
        }
648

649
        @SuppressWarnings("unchecked")
650
        public Chain<Object> fill(final Object value) {
651
            return new Chain<>(U.fill((List<Object>) value(), value));
1✔
652
        }
653

654
        @SuppressWarnings("unchecked")
655
        public Chain<Object> fill(final Object value, final Integer start, final Integer end) {
656
            return new Chain<>(U.fill((List<Object>) value(), value, start, end));
1✔
657
        }
658

659
        public Chain<Object> flattenDeep() {
660
            return new Chain<>(U.flattenDeep(value()));
1✔
661
        }
662

663
        @SuppressWarnings("unchecked")
664
        public Chain<Object> pull(final Object... values) {
665
            return new Chain<>(U.pull((List<Object>) value(), values));
1✔
666
        }
667

668
        @SuppressWarnings("unchecked")
669
        public Chain<Object> pullAt(final Integer... indexes) {
670
            return new Chain<>(U.pullAt((List<Object>) value(), indexes));
1✔
671
        }
672

673
        public Chain<T> remove(final Predicate<T> pred) {
674
            return new Chain<>(U.remove(value(), pred));
1✔
675
        }
676

677
        public Chain<T> take() {
678
            return new Chain<>(U.take(value()));
1✔
679
        }
680

681
        public Chain<T> takeRight() {
682
            return new Chain<>(U.takeRight(value()));
1✔
683
        }
684

685
        public Chain<T> take(final Integer n) {
686
            return new Chain<>(U.take(value(), n));
1✔
687
        }
688

689
        public Chain<T> takeRight(final Integer n) {
690
            return new Chain<>(U.takeRight(value(), n));
1✔
691
        }
692

693
        public Chain<T> takeWhile(final Predicate<T> pred) {
694
            return new Chain<>(U.takeWhile(value(), pred));
1✔
695
        }
696

697
        public Chain<T> takeRightWhile(final Predicate<T> pred) {
698
            return new Chain<>(U.takeRightWhile(value(), pred));
1✔
699
        }
700

701
        @SuppressWarnings("unchecked")
702
        public Chain<T> xor(final List<T> list) {
703
            return new Chain<>(U.xor(value(), list));
1✔
704
        }
705

706
        public Chain<T> at(final Integer... indexes) {
707
            return new Chain<>(U.at(value(), indexes));
1✔
708
        }
709

710
        @SuppressWarnings("unchecked")
711
        public <F extends Number> Chain<F> sum() {
712
            return new Chain<>(U.sum((List<F>) value()));
1✔
713
        }
714

715
        public <F extends Number> Chain<F> sum(final Function<T, F> func) {
716
            return new Chain<>(U.sum(value(), func));
1✔
717
        }
718

719
        @SuppressWarnings("unchecked")
720
        public Chain<Double> mean() {
721
            return new Chain<>(U.mean((List<Number>) value()));
1✔
722
        }
723

724
        @SuppressWarnings("unchecked")
725
        public Chain<Double> median() {
726
            return new Chain<>(U.median((List<Number>) value()));
1✔
727
        }
728

729
        public Chain<String> camelCase() {
730
            return new Chain<>(U.camelCase((String) item()));
1✔
731
        }
732

733
        public Chain<String> lowerFirst() {
734
            return new Chain<>(U.lowerFirst((String) item()));
1✔
735
        }
736

737
        public Chain<String> upperFirst() {
738
            return new Chain<>(U.upperFirst((String) item()));
1✔
739
        }
740

741
        public Chain<String> capitalize() {
742
            return new Chain<>(U.capitalize((String) item()));
1✔
743
        }
744

745
        public Chain<String> deburr() {
746
            return new Chain<>(U.deburr((String) item()));
1✔
747
        }
748

749
        public Chain<Boolean> endsWith(final String target) {
750
            return new Chain<>(U.endsWith((String) item(), target));
1✔
751
        }
752

753
        public Chain<Boolean> endsWith(final String target, final Integer position) {
754
            return new Chain<>(U.endsWith((String) item(), target, position));
1✔
755
        }
756

757
        public Chain<String> kebabCase() {
758
            return new Chain<>(U.kebabCase((String) item()));
1✔
759
        }
760

761
        public Chain<String> repeat(final int length) {
762
            return new Chain<>(U.repeat((String) item(), length));
1✔
763
        }
764

765
        public Chain<String> pad(final int length) {
766
            return new Chain<>(U.pad((String) item(), length));
1✔
767
        }
768

769
        public Chain<String> pad(final int length, final String chars) {
770
            return new Chain<>(U.pad((String) item(), length, chars));
1✔
771
        }
772

773
        public Chain<String> padStart(final int length) {
774
            return new Chain<>(U.padStart((String) item(), length));
1✔
775
        }
776

777
        public Chain<String> padStart(final int length, final String chars) {
778
            return new Chain<>(U.padStart((String) item(), length, chars));
1✔
779
        }
780

781
        public Chain<String> padEnd(final int length) {
782
            return new Chain<>(U.padEnd((String) item(), length));
1✔
783
        }
784

785
        public Chain<String> padEnd(final int length, final String chars) {
786
            return new Chain<>(U.padEnd((String) item(), length, chars));
1✔
787
        }
788

789
        public Chain<String> snakeCase() {
790
            return new Chain<>(U.snakeCase((String) item()));
1✔
791
        }
792

793
        public Chain<String> startCase() {
794
            return new Chain<>(U.startCase((String) item()));
1✔
795
        }
796

797
        public Chain<Boolean> startsWith(final String target) {
798
            return new Chain<>(U.startsWith((String) item(), target));
1✔
799
        }
800

801
        public Chain<Boolean> startsWith(final String target, final Integer position) {
802
            return new Chain<>(U.startsWith((String) item(), target, position));
1✔
803
        }
804

805
        public Chain<String> trim() {
806
            return new Chain<>(U.trim((String) item()));
1✔
807
        }
808

809
        public Chain<String> trim(final String chars) {
810
            return new Chain<>(U.trim((String) item(), chars));
1✔
811
        }
812

813
        public Chain<String> trimStart() {
814
            return new Chain<>(U.trimStart((String) item()));
1✔
815
        }
816

817
        public Chain<String> trimStart(final String chars) {
818
            return new Chain<>(U.trimStart((String) item(), chars));
1✔
819
        }
820

821
        public Chain<String> trimEnd() {
822
            return new Chain<>(U.trimEnd((String) item()));
1✔
823
        }
824

825
        public Chain<String> trunc() {
826
            return new Chain<>(U.trunc((String) item()));
1✔
827
        }
828

829
        public Chain<String> trunc(final int length) {
830
            return new Chain<>(U.trunc((String) item(), length));
1✔
831
        }
832

833
        public Chain<String> trimEnd(final String chars) {
834
            return new Chain<>(U.trimEnd((String) item(), chars));
1✔
835
        }
836

837
        public Chain<String> uncapitalize() {
838
            return new Chain<>(U.uncapitalize((String) item()));
1✔
839
        }
840

841
        public Chain<String> words() {
842
            return new Chain<>(U.words((String) item()));
1✔
843
        }
844

845
        public Chain<String> toJson() {
846
            return new Chain<>(Json.toJson(value()));
1✔
847
        }
848

849
        public Chain<Object> fromJson() {
850
            return new Chain<>(Json.fromJson((String) item()));
1✔
851
        }
852

853
        public Chain<String> toXml() {
854
            return new Chain<>(Xml.toXml(value()));
1✔
855
        }
856

857
        public Chain<Object> fromXml() {
858
            return new Chain<>(Xml.fromXml((String) item()));
1✔
859
        }
860

861
        public Chain<String> fetch() {
862
            return new Chain<>(U.fetch((String) item()).text());
1✔
863
        }
864

865
        public Chain<String> fetch(final String method, final String body) {
866
            return new Chain<>(U.fetch((String) item(), method, body).text());
1✔
867
        }
868

869
        public Chain<List<T>> createPermutationWithRepetition(final int permutationLength) {
870
            return new Chain<>(U.createPermutationWithRepetition(value(), permutationLength));
1✔
871
        }
872

873
        public Chain<String> xmlToJson() {
874
            return new Chain<>(U.xmlToJson((String) item()));
1✔
875
        }
876

877
        public Chain<String> jsonToXml() {
878
            return new Chain<>(U.jsonToXml((String) item()));
1✔
879
        }
880
    }
881

882
    public static Chain<String> chain(final String item) {
883
        return new U.Chain<>(item);
1✔
884
    }
885

886
    public static <T> Chain<T> chain(final List<T> list) {
887
        return new U.Chain<>(list);
1✔
888
    }
889

890
    public static Chain<Map<String, Object>> chain(final Map<String, Object> map) {
891
        return new U.Chain<>(map);
1✔
892
    }
893

894
    public static <T> Chain<T> chain(final Iterable<T> iterable) {
895
        return new U.Chain<>(newArrayList(iterable));
1✔
896
    }
897

898
    public static <T> Chain<T> chain(final Iterable<T> iterable, int size) {
899
        return new U.Chain<>(newArrayList(iterable, size));
1✔
900
    }
901

902
    @SuppressWarnings("unchecked")
903
    public static <T> Chain<T> chain(final T... list) {
904
        return new U.Chain<>(Arrays.asList(list));
1✔
905
    }
906

907
    public static Chain<Integer> chain(final int[] array) {
908
        return new U.Chain<>(newIntegerList(array));
1✔
909
    }
910

911
    @Override
912
    public Chain<T> chain() {
913
        return new U.Chain<>(newArrayList(value()));
1✔
914
    }
915

916
    public static Chain<String> of(final String item) {
917
        return new U.Chain<>(item);
1✔
918
    }
919

920
    public static <T> Chain<T> of(final List<T> list) {
921
        return new U.Chain<>(list);
1✔
922
    }
923

924
    public static Chain<Map<String, Object>> of(final Map<String, Object> map) {
925
        return new U.Chain<>(map);
1✔
926
    }
927

928
    public static <T> Chain<T> of(final Iterable<T> iterable) {
929
        return new U.Chain<>(newArrayList(iterable));
1✔
930
    }
931

932
    public static <T> Chain<T> of(final Iterable<T> iterable, int size) {
933
        return new U.Chain<>(newArrayList(iterable, size));
1✔
934
    }
935

936
    @SuppressWarnings("unchecked")
937
    public static <T> Chain<T> of(final T... list) {
938
        return new U.Chain<>(Arrays.asList(list));
1✔
939
    }
940

941
    public static Chain<Integer> of(final int[] array) {
942
        return new U.Chain<>(newIntegerList(array));
1✔
943
    }
944

945
    @Override
946
    public Chain<T> of() {
947
        return new U.Chain<>(newArrayList(value()));
1✔
948
    }
949

950
    public static <T> List<T> drop(final Iterable<T> iterable) {
951
        return rest(newArrayList(iterable));
1✔
952
    }
953

954
    public List<T> drop() {
955
        return drop(getIterable());
1✔
956
    }
957

958
    public static <T> List<T> drop(final Iterable<T> iterable, final Integer n) {
959
        return rest(newArrayList(iterable), n);
1✔
960
    }
961

962
    public List<T> drop(final Integer n) {
963
        return drop(getIterable(), n);
1✔
964
    }
965

966
    public static <T> List<T> dropRight(final Iterable<T> iterable) {
967
        return initial(newArrayList(iterable));
1✔
968
    }
969

970
    public List<T> dropRight() {
971
        return dropRight(getIterable());
1✔
972
    }
973

974
    public static <T> List<T> dropRight(final Iterable<T> iterable, final Integer n) {
975
        return initial(newArrayList(iterable), n);
1✔
976
    }
977

978
    public List<T> dropRight(final Integer n) {
979
        return dropRight(getIterable(), n);
1✔
980
    }
981

982
    public static <T> List<T> dropWhile(final Iterable<T> iterable, final Predicate<T> pred) {
983
        return rest(newArrayList(iterable), findIndex(newArrayList(iterable), negate(pred)));
1✔
984
    }
985

986
    public List<T> dropWhile(final Predicate<T> pred) {
987
        return dropWhile(getIterable(), pred);
1✔
988
    }
989

990
    public static <T> List<T> dropRightWhile(final Iterable<T> iterable, final Predicate<T> pred) {
991
        return reverse(dropWhile(reverse(iterable), pred));
1✔
992
    }
993

994
    public List<T> dropRightWhile(final Predicate<T> pred) {
995
        return dropRightWhile(getIterable(), pred);
1✔
996
    }
997

998
    public static <T> List<T> fill(List<T> list, T item) {
999
        for (int i = 0; i < size(list); i++) {
1✔
1000
            list.set(i, item);
1✔
1001
        }
1002
        return list;
1✔
1003
    }
1004

1005
    public static <T> T[] fill(T[] array, T item) {
1006
        Arrays.fill(array, item);
1✔
1007
        return array;
1✔
1008
    }
1009

1010
    @SuppressWarnings("unchecked")
1011
    public List<Object> fill(Object value) {
1012
        return fill((List<Object>) getIterable(), value);
1✔
1013
    }
1014

1015
    public static List<Object> fill(
1016
            final List<Object> list, Object value, Integer start, Integer end) {
1017
        for (int index = start; index < end; index += 1) {
1✔
1018
            list.set(index, value);
1✔
1019
        }
1020
        return list;
1✔
1021
    }
1022

1023
    @SuppressWarnings("unchecked")
1024
    public List<Object> fill(Object value, Integer start, Integer end) {
1025
        return fill((List<Object>) getIterable(), value, start, end);
1✔
1026
    }
1027

1028
    public static <E> List<E> flattenDeep(final List<?> list) {
1029
        return flatten(list, false);
1✔
1030
    }
1031

1032
    public List<T> flattenDeep() {
1033
        return flattenDeep((List<?>) getIterable());
1✔
1034
    }
1035

1036
    public static List<Object> pull(final List<Object> list, Object... values) {
1037
        final List<Object> valuesList = Arrays.asList(values);
1✔
1038
        list.removeIf(valuesList::contains);
1✔
1039
        return list;
1✔
1040
    }
1041

1042
    @SuppressWarnings("unchecked")
1043
    public List<Object> pull(Object... values) {
1044
        return pull((List<Object>) getIterable(), values);
1✔
1045
    }
1046

1047
    public static List<Object> pullAt(final List<Object> list, final Integer... indexes) {
1048
        final List<Object> result = new ArrayList<>();
1✔
1049
        final List<Integer> indexesList = Arrays.asList(indexes);
1✔
1050
        int index = 0;
1✔
1051
        for (final Iterator<Object> iterator = list.iterator(); iterator.hasNext(); ) {
1✔
1052
            final Object object = iterator.next();
1✔
1053
            if (indexesList.contains(index)) {
1✔
1054
                result.add(object);
1✔
1055
                iterator.remove();
1✔
1056
            }
1057
            index += 1;
1✔
1058
        }
1✔
1059
        return result;
1✔
1060
    }
1061

1062
    @SuppressWarnings("unchecked")
1063
    public List<Object> pullAt(final Integer... indexes) {
1064
        return pullAt((List<Object>) getIterable(), indexes);
1✔
1065
    }
1066

1067
    public static <T> List<T> remove(final List<T> list, final Predicate<T> pred) {
1068
        final List<T> result = new ArrayList<>();
1✔
1069
        for (final Iterator<T> iterator = list.iterator(); iterator.hasNext(); ) {
1✔
1070
            final T object = iterator.next();
1✔
1071
            if (pred.test(object)) {
1✔
1072
                result.add(object);
1✔
1073
                iterator.remove();
1✔
1074
            }
1075
        }
1✔
1076
        return result;
1✔
1077
    }
1078

1079
    public List<T> remove(final Predicate<T> pred) {
1080
        return remove((List<T>) getIterable(), pred);
1✔
1081
    }
1082

1083
    public static <T> List<T> take(final Iterable<T> iterable) {
1084
        return first(newArrayList(iterable), 1);
1✔
1085
    }
1086

1087
    public List<T> take() {
1088
        return take(getIterable());
1✔
1089
    }
1090

1091
    public static <T> List<T> takeRight(final Iterable<T> iterable) {
1092
        return last(newArrayList(iterable), 1);
1✔
1093
    }
1094

1095
    public List<T> takeRight() {
1096
        return takeRight(getIterable());
1✔
1097
    }
1098

1099
    public static <T> List<T> take(final Iterable<T> iterable, final Integer n) {
1100
        return first(newArrayList(iterable), n);
1✔
1101
    }
1102

1103
    public List<T> take(final Integer n) {
1104
        return take(getIterable(), n);
1✔
1105
    }
1106

1107
    public static <T> List<T> takeRight(final Iterable<T> iterable, final Integer n) {
1108
        return last(newArrayList(iterable), n);
1✔
1109
    }
1110

1111
    public List<T> takeRight(final Integer n) {
1112
        return takeRight(getIterable(), n);
1✔
1113
    }
1114

1115
    public static <T> List<T> takeWhile(final Iterable<T> iterable, final Predicate<T> pred) {
1116
        return first(newArrayList(iterable), findIndex(newArrayList(iterable), negate(pred)));
1✔
1117
    }
1118

1119
    public List<T> takeWhile(final Predicate<T> pred) {
1120
        return takeWhile(getIterable(), pred);
1✔
1121
    }
1122

1123
    public static <T> List<T> takeRightWhile(final Iterable<T> iterable, final Predicate<T> pred) {
1124
        return reverse(takeWhile(reverse(iterable), pred));
1✔
1125
    }
1126

1127
    public List<T> takeRightWhile(final Predicate<T> pred) {
1128
        return takeRightWhile(getIterable(), pred);
1✔
1129
    }
1130

1131
    @SuppressWarnings("unchecked")
1132
    public static <T> List<T> xor(final List<T>... lists) {
1133
        int index = -1;
1✔
1134
        int length = lists.length;
1✔
1135
        List<T> result = null;
1✔
1136
        while (++index < length) {
1✔
1137
            final List<T> array = lists[index];
1✔
1138
            result =
1139
                    result == null
1✔
1140
                            ? array
1✔
1141
                            : concat(difference(result, array), difference(array, result));
1✔
1142
        }
1✔
1143
        return uniq(result);
1✔
1144
    }
1145

1146
    @SuppressWarnings("unchecked")
1147
    public List<T> xor(final List<T> list) {
1148
        return xor((List<T>) getIterable(), list);
1✔
1149
    }
1150

1151
    public static <T> List<T> at(final List<T> list, final Integer... indexes) {
1152
        final List<T> result = new ArrayList<>();
1✔
1153
        final List<Integer> indexesList = Arrays.asList(indexes);
1✔
1154
        int index = 0;
1✔
1155
        for (final T object : list) {
1✔
1156
            if (indexesList.contains(index)) {
1✔
1157
                result.add(object);
1✔
1158
            }
1159
            index += 1;
1✔
1160
        }
1✔
1161
        return result;
1✔
1162
    }
1163

1164
    public List<T> at(final Integer... indexes) {
1165
        return at((List<T>) getIterable(), indexes);
1✔
1166
    }
1167

1168
    public static <T extends Number> Double average(final Iterable<T> iterable) {
1169
        T sum = sum(iterable);
1✔
1170
        if (sum == null) {
1✔
1171
            return null;
1✔
1172
        }
1173
        return sum.doubleValue() / size(iterable);
1✔
1174
    }
1175

1176
    public static <E, F extends Number> Double average(
1177
            final Iterable<E> iterable, final Function<E, F> func) {
1178
        F sum = sum(iterable, func);
1✔
1179
        if (sum == null) {
1✔
1180
            return null;
1✔
1181
        }
1182
        return sum.doubleValue() / size(iterable);
1✔
1183
    }
1184

1185
    public static <N extends Number> Double average(N[] array) {
1186
        N sum = sum(array);
1✔
1187
        if (sum == null) {
1✔
1188
            return null;
1✔
1189
        }
1190
        return sum.doubleValue() / array.length;
1✔
1191
    }
1192

1193
    public static Double average(java.math.BigDecimal first, java.math.BigDecimal second) {
1194
        if (first == null || second == null) {
1✔
1195
            return null;
1✔
1196
        }
1197
        return sum(first, second).doubleValue() / 2;
1✔
1198
    }
1199

1200
    public static Double average(java.math.BigInteger first, java.math.BigInteger second) {
1201
        if (first == null || second == null) {
1✔
1202
            return null;
1✔
1203
        }
1204
        return sum(first, second).doubleValue() / 2;
1✔
1205
    }
1206

1207
    public static Double average(Byte first, Byte second) {
1208
        if (first == null || second == null) {
1✔
1209
            return null;
1✔
1210
        }
1211
        return sum(first, second).doubleValue() / 2;
1✔
1212
    }
1213

1214
    public static Double average(Double first, Double second) {
1215
        if (first == null || second == null) {
1✔
1216
            return null;
1✔
1217
        }
1218
        return sum(first, second) / 2;
1✔
1219
    }
1220

1221
    public static Double average(Float first, Float second) {
1222
        if (first == null || second == null) {
1✔
1223
            return null;
1✔
1224
        }
1225
        return sum(first, second).doubleValue() / 2;
1✔
1226
    }
1227

1228
    public static Double average(Integer first, Integer second) {
1229
        if (first == null || second == null) {
1✔
1230
            return null;
1✔
1231
        }
1232
        return sum(first, second).doubleValue() / 2;
1✔
1233
    }
1234

1235
    public static Double average(Long first, Long second) {
1236
        if (first == null || second == null) {
1✔
1237
            return null;
1✔
1238
        }
1239
        return sum(first, second).doubleValue() / 2;
1✔
1240
    }
1241

1242
    public static <T extends Number> T sum(final Iterable<T> iterable) {
1243
        T result = null;
1✔
1244
        for (final T item : iterable) {
1✔
1245
            result = add(result, item);
1✔
1246
        }
1✔
1247
        return result;
1✔
1248
    }
1249

1250
    public static <E, F extends Number> F sum(
1251
            final Iterable<E> iterable, final Function<E, F> func) {
1252
        F result = null;
1✔
1253
        for (final E item : iterable) {
1✔
1254
            result = add(result, func.apply(item));
1✔
1255
        }
1✔
1256
        return result;
1✔
1257
    }
1258

1259
    public static <N extends Number> N sum(N[] array) {
1260
        N result = null;
1✔
1261
        for (final N item : array) {
1✔
1262
            result = add(result, item);
1✔
1263
        }
1264
        return result;
1✔
1265
    }
1266

1267
    @SuppressWarnings("unchecked")
1268
    public <F extends Number> F sum() {
1269
        return sum((List<F>) getIterable());
1✔
1270
    }
1271

1272
    @SuppressWarnings("unchecked")
1273
    public <E, F extends Number> F sum(final Function<E, F> func) {
1274
        return sum((List<E>) getIterable(), func);
1✔
1275
    }
1276

1277
    @SuppressWarnings("unchecked")
1278
    public static <T extends Number> T add(final T first, final T second) {
1279
        if (first == null) {
1✔
1280
            return second;
1✔
1281
        } else if (second == null) {
1✔
1282
            return first;
1✔
1283
        } else if (first instanceof java.math.BigDecimal) {
1✔
1284
            return (T) sum((java.math.BigDecimal) first, (java.math.BigDecimal) second);
1✔
1285
        } else if (second instanceof java.math.BigInteger) {
1✔
1286
            return (T) sum((java.math.BigInteger) first, (java.math.BigInteger) second);
1✔
1287
        } else if (first instanceof Byte) {
1✔
1288
            return (T) sum((Byte) first, (Byte) second);
1✔
1289
        } else if (first instanceof Double) {
1✔
1290
            return (T) sum((Double) first, (Double) second);
1✔
1291
        } else if (first instanceof Float) {
1✔
1292
            return (T) sum((Float) first, (Float) second);
1✔
1293
        } else if (first instanceof Integer) {
1✔
1294
            return (T) sum((Integer) first, (Integer) second);
1✔
1295
        } else if (first instanceof Long) {
1✔
1296
            return (T) sum((Long) first, (Long) second);
1✔
1297
        } else if (first instanceof Short) {
1✔
1298
            return (T) sum((Short) first, (Short) second);
1✔
1299
        } else {
1300
            throw new UnsupportedOperationException(
1✔
1301
                    "Sum only supports official subclasses of Number");
1302
        }
1303
    }
1304

1305
    private static java.math.BigDecimal sum(
1306
            java.math.BigDecimal first, java.math.BigDecimal second) {
1307
        return first.add(second);
1✔
1308
    }
1309

1310
    private static java.math.BigInteger sum(
1311
            java.math.BigInteger first, java.math.BigInteger second) {
1312
        return first.add(second);
1✔
1313
    }
1314

1315
    private static Byte sum(Byte first, Byte second) {
1316
        return (byte) (first + second);
1✔
1317
    }
1318

1319
    private static Double sum(Double first, Double second) {
1320
        return first + second;
1✔
1321
    }
1322

1323
    private static Float sum(Float first, Float second) {
1324
        return first + second;
1✔
1325
    }
1326

1327
    private static Integer sum(Integer first, Integer second) {
1328
        return first + second;
1✔
1329
    }
1330

1331
    private static Long sum(Long first, Long second) {
1332
        return first + second;
1✔
1333
    }
1334

1335
    private static Short sum(Short first, Short second) {
1336
        return (short) (first + second);
1✔
1337
    }
1338

1339
    @SuppressWarnings("unchecked")
1340
    public static <T extends Number> T subtract(final T... values) {
1341
        if (values.length == 0) {
1✔
1342
            return null;
1✔
1343
        }
1344
        T result = values[0];
1✔
1345
        for (int i = 1; i < values.length; i++) {
1✔
1346
            if (result instanceof java.math.BigDecimal) {
1✔
1347
                java.math.BigDecimal value = (java.math.BigDecimal) values[i];
1✔
1348
                result = add(result, (T) value.negate());
1✔
1349
            } else if (result instanceof java.math.BigInteger) {
1✔
1350
                java.math.BigInteger value = (java.math.BigInteger) values[i];
1✔
1351
                result = add(result, (T) value.negate());
1✔
1352
            } else if (result instanceof Byte) {
1✔
1353
                result = add(result, (T) Byte.valueOf((byte) (values[i].byteValue() * -1)));
1✔
1354
            } else if (result instanceof Double) {
1✔
1355
                result = add(result, (T) Double.valueOf(values[i].doubleValue() * -1));
1✔
1356
            } else if (result instanceof Float) {
1✔
1357
                result = add(result, (T) Float.valueOf(values[i].floatValue() * -1));
1✔
1358
            } else if (result instanceof Integer) {
1✔
1359
                result = add(result, (T) Integer.valueOf(values[i].intValue() * -1));
1✔
1360
            } else if (result instanceof Long) {
1✔
1361
                result = add(result, (T) Long.valueOf(values[i].longValue() * -1));
1✔
1362
            } else if (result instanceof Short) {
1✔
1363
                result = add(result, (T) Short.valueOf((short) (values[i].shortValue() * -1)));
1✔
1364
            } else {
1365
                throw new UnsupportedOperationException(
1✔
1366
                        "Subtract only supports official subclasses of Number");
1367
            }
1368
        }
1369
        return result;
1✔
1370
    }
1371

1372
    public static <T extends Number> double mean(final Iterable<T> iterable) {
1373
        T result = null;
1✔
1374
        int count = 0;
1✔
1375
        for (final T item : iterable) {
1✔
1376
            result = add(result, item);
1✔
1377
            count += 1;
1✔
1378
        }
1✔
1379
        if (result == null) {
1✔
1380
            return 0d;
1✔
1381
        }
1382
        return result.doubleValue() / count;
1✔
1383
    }
1384

1385
    @SuppressWarnings("unchecked")
1386
    public double mean() {
1387
        return mean((Iterable<Number>) getIterable());
1✔
1388
    }
1389

1390
    @SuppressWarnings("unchecked")
1391
    public static <T extends Number> double median(final Iterable<T> iterable) {
1392
        final List<T> result = newArrayList((Collection) iterable);
1✔
1393
        final int size = size(iterable);
1✔
1394
        if (size == 0) {
1✔
1395
            throw new IllegalArgumentException("Iterable cannot be empty");
1✔
1396
        }
1397
        if (size % 2 != 0) {
1✔
1398
            return result.get(size / 2).doubleValue();
1✔
1399
        }
1400
        return (result.get(size / 2 - 1).doubleValue() + result.get(size / 2).doubleValue()) / 2;
1✔
1401
    }
1402

1403
    @SuppressWarnings("unchecked")
1404
    public double median() {
1405
        return median((Iterable<Number>) getIterable());
1✔
1406
    }
1407

1408
    public static String camelCase(final String string) {
1409
        return createCompounder(
1✔
1410
                        (result, word, index) -> {
1411
                            final String localWord = word.toLowerCase(Locale.getDefault());
1✔
1412
                            return result
1✔
1413
                                    + (index > 0
1✔
1414
                                            ? localWord
1415
                                                            .substring(0, 1)
1✔
1416
                                                            .toUpperCase(Locale.getDefault())
1✔
1417
                                                    + localWord.substring(1)
1✔
1418
                                            : localWord);
1✔
1419
                        })
1420
                .apply(string);
1✔
1421
    }
1422

1423
    public static String lowerFirst(final String string) {
1424
        return createCaseFirst("toLowerCase").apply(string);
1✔
1425
    }
1426

1427
    public static String upperFirst(final String string) {
1428
        return createCaseFirst("toUpperCase").apply(string);
1✔
1429
    }
1430

1431
    public static String capitalize(final String string) {
1432
        return upperFirst(baseToString(string));
1✔
1433
    }
1434

1435
    public static String uncapitalize(final String string) {
1436
        return lowerFirst(baseToString(string));
1✔
1437
    }
1438

1439
    private static String baseToString(String value) {
1440
        return value == null ? "" : value;
1✔
1441
    }
1442

1443
    public static String deburr(final String string) {
1444
        final String localString = baseToString(string);
1✔
1445
        final StringBuilder sb = new StringBuilder();
1✔
1446
        for (final String str : localString.split("")) {
1✔
1447
            if (RE_LATIN_1.matcher(str).matches()) {
1✔
1448
                sb.append(DEBURRED_LETTERS.get(str));
1✔
1449
            } else {
1450
                sb.append(str);
1✔
1451
            }
1452
        }
1453
        return sb.toString();
1✔
1454
    }
1455

1456
    public static List<String> words(final String string) {
1457
        final String localString = baseToString(string);
1✔
1458
        final List<String> result = new ArrayList<>();
1✔
1459
        final java.util.regex.Matcher matcher = RE_WORDS.matcher(localString);
1✔
1460
        while (matcher.find()) {
1✔
1461
            result.add(matcher.group());
1✔
1462
        }
1463
        return result;
1✔
1464
    }
1465

1466
    private static Function<String, String> createCompounder(
1467
            final Function3<String, String, Integer, String> callback) {
1468
        return string -> {
1✔
1469
            int index = -1;
1✔
1470
            List<String> array = words(deburr(string));
1✔
1471
            int length = array.size();
1✔
1472
            String result = "";
1✔
1473

1474
            while (++index < length) {
1✔
1475
                result = callback.apply(result, array.get(index), index);
1✔
1476
            }
1477
            return result;
1✔
1478
        };
1479
    }
1480

1481
    private static Function<String, String> createCaseFirst(final String methodName) {
1482
        return string -> {
1✔
1483
            final String localString = baseToString(string);
1✔
1484
            final String chr = localString.isEmpty() ? "" : localString.substring(0, 1);
1✔
1485
            final String trailing = localString.length() > 1 ? localString.substring(1) : "";
1✔
1486
            return Underscore.invoke(Collections.singletonList(chr), methodName).get(0) + trailing;
1✔
1487
        };
1488
    }
1489

1490
    public static boolean endsWith(final String string, final String target) {
1491
        return endsWith(string, target, null);
1✔
1492
    }
1493

1494
    public static boolean endsWith(
1495
            final String string, final String target, final Integer position) {
1496
        if (string == null || target == null) {
1✔
1497
            return false;
1✔
1498
        }
1499
        final String localString = baseToString(string);
1✔
1500

1501
        final int length = localString.length();
1✔
1502
        final int fixedPosition = position == null || position < 0 ? 0 : position;
1✔
1503
        final int localPosition = position == null ? length : Math.min(fixedPosition, length);
1✔
1504

1505
        final int localPosition2 = localPosition - target.length();
1✔
1506
        return localPosition2 >= 0 && localString.indexOf(target, localPosition2) == localPosition2;
1✔
1507
    }
1508

1509
    public static String kebabCase(final String string) {
1510
        return createCompounder(
1✔
1511
                        (result, word, index) ->
1512
                                result
1✔
1513
                                        + (index > 0 ? "-" : "")
1✔
1514
                                        + word.toLowerCase(Locale.getDefault()))
1✔
1515
                .apply(string);
1✔
1516
    }
1517

1518
    public static String repeat(final String string, final int length) {
1519
        final StringBuilder result = new StringBuilder();
1✔
1520
        final StringBuilder localString = new StringBuilder(baseToString(string));
1✔
1521
        if (length < 1 || string == null) {
1✔
1522
            return result.toString();
1✔
1523
        }
1524
        int n = length;
1✔
1525
        do {
1526
            if (n % 2 != 0) {
1✔
1527
                result.append(localString);
1✔
1528
            }
1529
            n = (int) Math.floor(n / (double) 2);
1✔
1530
            localString.append(localString);
1✔
1531
        } while (n > 0);
1✔
1532
        return result.toString();
1✔
1533
    }
1534

1535
    private static String createPadding(final String string, final int length, final String chars) {
1536
        final int strLength = string.length();
1✔
1537
        final int padLength = length - strLength;
1✔
1538
        final String localChars = chars == null ? " " : chars;
1✔
1539
        return repeat(localChars, (int) Math.ceil(padLength / (double) localChars.length()))
1✔
1540
                .substring(0, padLength);
1✔
1541
    }
1542

1543
    public static String pad(final String string, final int length) {
1544
        return pad(string, length, null);
1✔
1545
    }
1546

1547
    public static String pad(final String string, final int length, final String chars) {
1548
        final String localString = baseToString(string);
1✔
1549
        final int strLength = localString.length();
1✔
1550
        if (strLength >= length) {
1✔
1551
            return localString;
1✔
1552
        }
1553
        final double mid = (length - strLength) / (double) 2;
1✔
1554
        final int leftLength = (int) Math.floor(mid);
1✔
1555
        final int rightLength = (int) Math.ceil(mid);
1✔
1556
        final String localChars = createPadding("", rightLength, chars);
1✔
1557
        return localChars.substring(0, leftLength) + localString + localChars;
1✔
1558
    }
1559

1560
    private static Function3<String, Integer, String, String> createPadDir(
1561
            final boolean fromRight) {
1562
        return (string, length, chars) -> {
1✔
1563
            final String localString = baseToString(string);
1✔
1564
            return (fromRight ? localString : "")
1✔
1565
                    + createPadding(localString, length, chars)
1✔
1566
                    + (fromRight ? "" : localString);
1✔
1567
        };
1568
    }
1569

1570
    public static String padStart(final String string, final Integer length) {
1571
        return createPadDir(false).apply(string, length, null);
1✔
1572
    }
1573

1574
    public static String padStart(final String string, final Integer length, final String chars) {
1575
        return createPadDir(false).apply(string, length, chars);
1✔
1576
    }
1577

1578
    public static String padEnd(final String string, final Integer length) {
1579
        return createPadDir(true).apply(string, length, null);
1✔
1580
    }
1581

1582
    public static String padEnd(final String string, final Integer length, final String chars) {
1583
        return createPadDir(true).apply(string, length, chars);
1✔
1584
    }
1585

1586
    public static String snakeCase(final String string) {
1587
        return createCompounder(
1✔
1588
                        (result, word, index) ->
1589
                                result
1✔
1590
                                        + (index > 0 ? "_" : "")
1✔
1591
                                        + word.toLowerCase(Locale.getDefault()))
1✔
1592
                .apply(string);
1✔
1593
    }
1594

1595
    public static String startCase(final String string) {
1596
        return createCompounder(
1✔
1597
                        (result, word, index) ->
1598
                                result
1✔
1599
                                        + (index > 0 ? " " : "")
1✔
1600
                                        + word.substring(0, 1).toUpperCase(Locale.getDefault())
1✔
1601
                                        + word.substring(1))
1✔
1602
                .apply(string);
1✔
1603
    }
1604

1605
    public static boolean startsWith(final String string, final String target) {
1606
        return startsWith(string, target, null);
1✔
1607
    }
1608

1609
    public static boolean startsWith(
1610
            final String string, final String target, final Integer position) {
1611
        if (string == null || target == null) {
1✔
1612
            return false;
1✔
1613
        }
1614
        final String localString = baseToString(string);
1✔
1615

1616
        final int length = localString.length();
1✔
1617
        final int localPosition;
1618
        if (position == null) {
1✔
1619
            localPosition = 0;
1✔
1620
        } else {
1621
            final int from = position < 0 ? 0 : position;
1✔
1622
            localPosition = Math.min(from, length);
1✔
1623
        }
1624

1625
        return localString.lastIndexOf(target, localPosition) == localPosition;
1✔
1626
    }
1627

1628
    private static int charsLeftIndex(final String string, final String chars) {
1629
        int index = 0;
1✔
1630
        final int length = string.length();
1✔
1631
        while (index < length && chars.indexOf(string.charAt(index)) > -1) {
1✔
1632
            index += 1;
1✔
1633
        }
1634
        return index == length ? -1 : index;
1✔
1635
    }
1636

1637
    private static int charsRightIndex(final String string, final String chars) {
1638
        int index = string.length() - 1;
1✔
1639
        while (index >= 0 && chars.indexOf(string.charAt(index)) > -1) {
1✔
1640
            index -= 1;
1✔
1641
        }
1642
        return index;
1✔
1643
    }
1644

1645
    public static String trim(final String string) {
1646
        return trim(string, null);
1✔
1647
    }
1648

1649
    public static String trim(final String string, final String chars) {
1650
        final String localString = baseToString(string);
1✔
1651
        if (localString.isEmpty()) {
1✔
1652
            return localString;
1✔
1653
        }
1654
        final String localChars;
1655
        if (chars == null) {
1✔
1656
            localChars = " ";
1✔
1657
        } else {
1658
            localChars = chars;
1✔
1659
        }
1660
        final int leftIndex = charsLeftIndex(localString, localChars);
1✔
1661
        final int rightIndex = charsRightIndex(localString, localChars);
1✔
1662
        return leftIndex > -1 ? localString.substring(leftIndex, rightIndex + 1) : localString;
1✔
1663
    }
1664

1665
    public static String trimStart(final String string) {
1666
        return trimStart(string, null);
1✔
1667
    }
1668

1669
    public static String trimStart(final String string, final String chars) {
1670
        final String localString = baseToString(string);
1✔
1671
        if (localString.isEmpty()) {
1✔
1672
            return localString;
1✔
1673
        }
1674
        final String localChars;
1675
        if (chars == null) {
1✔
1676
            localChars = " ";
1✔
1677
        } else {
1678
            localChars = chars;
1✔
1679
        }
1680
        final int leftIndex = charsLeftIndex(localString, localChars);
1✔
1681
        return leftIndex > -1 ? localString.substring(leftIndex) : localString;
1✔
1682
    }
1683

1684
    public static String trimEnd(final String string) {
1685
        return trimEnd(string, null);
1✔
1686
    }
1687

1688
    public static String trimEnd(final String string, final String chars) {
1689
        final String localString = baseToString(string);
1✔
1690
        if (localString.isEmpty()) {
1✔
1691
            return localString;
1✔
1692
        }
1693
        final String localChars;
1694
        if (chars == null) {
1✔
1695
            localChars = " ";
1✔
1696
        } else {
1697
            localChars = chars;
1✔
1698
        }
1699
        final int rightIndex = charsRightIndex(localString, localChars);
1✔
1700
        return rightIndex > -1 ? localString.substring(0, rightIndex + 1) : localString;
1✔
1701
    }
1702

1703
    public static String trunc(final String string) {
1704
        return trunc(string, DEFAULT_TRUNC_LENGTH);
1✔
1705
    }
1706

1707
    public static String trunc(final String string, final Integer length) {
1708
        final String localString = baseToString(string);
1✔
1709
        final String omission = DEFAULT_TRUNC_OMISSION;
1✔
1710
        if (length >= localString.length()) {
1✔
1711
            return localString;
1✔
1712
        }
1713
        final int end = length - omission.length();
1✔
1714
        final String result = localString.substring(0, end);
1✔
1715
        return result + omission;
1✔
1716
    }
1717

1718
    public static List<String> stringToPath(final String string) {
1719
        final List<String> result = new ArrayList<>();
1✔
1720
        final java.util.regex.Matcher matcher = RE_PROP_NAME.matcher(baseToString(string));
1✔
1721
        while (matcher.find()) {
1✔
1722
            result.add(matcher.group(1) == null ? matcher.group(0) : matcher.group(1));
1✔
1723
        }
1724
        return result;
1✔
1725
    }
1726

1727
    private enum OperationType {
1✔
1728
        GET,
1✔
1729
        SET,
1✔
1730
        UPDATE,
1✔
1731
        REMOVE
1✔
1732
    }
1733

1734
    @SuppressWarnings("unchecked")
1735
    private static <T> T baseGetOrSetOrRemove(
1736
            final Map<String, Object> object,
1737
            final List<String> paths,
1738
            final Object value,
1739
            OperationType operationType) {
1740
        int index = 0;
1✔
1741
        final int length = paths.size();
1✔
1742

1743
        Object localObject = object;
1✔
1744
        Object savedLocalObject = null;
1✔
1745
        String savedPath = null;
1✔
1746
        while (localObject != null && index < length) {
1✔
1747
            if (localObject instanceof Map) {
1✔
1748
                Map.Entry mapEntry = getMapEntry((Map) localObject);
1✔
1749
                if (mapEntry != null && "#item".equals(mapEntry.getKey())) {
1✔
1750
                    localObject = mapEntry.getValue();
1✔
1751
                    continue;
1✔
1752
                }
1753
                savedLocalObject = localObject;
1✔
1754
                savedPath = paths.get(index);
1✔
1755
                localObject = ((Map) localObject).get(paths.get(index));
1✔
1756
            } else if (localObject instanceof List) {
1✔
1757
                savedLocalObject = localObject;
1✔
1758
                savedPath = paths.get(index);
1✔
1759
                localObject = ((List) localObject).get(Integer.parseInt(paths.get(index)));
1✔
1760
            } else {
1761
                break;
1762
            }
1763
            index += 1;
1✔
1764
        }
1765
        if (index > 0 && index == length) {
1✔
1766
            checkSetAndRemove(value, operationType, savedLocalObject, savedPath);
1✔
1767
            return (T) localObject;
1✔
1768
        }
1769
        return null;
1✔
1770
    }
1771

1772
    @SuppressWarnings("unchecked")
1773
    private static void checkSetAndRemove(
1774
            Object value, OperationType operationType, Object savedLocalObject, String savedPath) {
1775
        if (operationType == OperationType.SET || operationType == OperationType.UPDATE) {
1✔
1776
            if (savedLocalObject instanceof Map) {
1✔
1777
                checkSetOrUpdate(
1✔
1778
                        value, operationType, (Map<String, Object>) savedLocalObject, savedPath);
1779
            } else {
1780
                ((List) savedLocalObject).set(Integer.parseInt(savedPath), value);
1✔
1781
            }
1782
        } else if (operationType == OperationType.REMOVE) {
1✔
1783
            if (savedLocalObject instanceof Map) {
1✔
1784
                ((Map) savedLocalObject).remove(savedPath);
1✔
1785
            } else {
1786
                ((List) savedLocalObject).remove(Integer.parseInt(savedPath));
1✔
1787
            }
1788
        }
1789
    }
1✔
1790

1791
    private static void checkSetOrUpdate(
1792
            Object value,
1793
            OperationType operationType,
1794
            Map<String, Object> savedLocalObject,
1795
            String savedPath) {
1796
        if (operationType == OperationType.UPDATE && savedLocalObject.containsKey(savedPath)) {
1✔
1797
            savedLocalObject.put(Underscore.uniqueId(savedPath), value);
1✔
1798
        } else {
1799
            savedLocalObject.put(savedPath, value);
1✔
1800
        }
1801
    }
1✔
1802

1803
    private static Map.Entry getMapEntry(Map map) {
1804
        return map.isEmpty() ? null : (Map.Entry) map.entrySet().iterator().next();
1✔
1805
    }
1806

1807
    public static <T> T get(final Map<String, Object> object, final String path) {
1808
        return get(object, stringToPath(path));
1✔
1809
    }
1810

1811
    public static <T> T get(final Map<String, Object> object, final List<String> paths) {
1812
        return baseGetOrSetOrRemove(object, paths, null, OperationType.GET);
1✔
1813
    }
1814

1815
    public static String selectToken(final Map<String, Object> object, final String expression) {
1816
        final String xml = toXml(object);
1✔
1817
        try {
1818
            final XPath xPath = XPathFactory.newInstance().newXPath();
1✔
1819
            final org.w3c.dom.Document document = Xml.Document.createDocument(xml);
1✔
1820
            final NodeList nodes =
1✔
1821
                    (NodeList) xPath.compile(expression).evaluate(document, XPathConstants.NODESET);
1✔
1822
            if (nodes.getLength() == 0) {
1✔
1823
                return null;
1✔
1824
            }
1825
            return nodes.item(0).getNodeValue();
1✔
1826
        } catch (Exception ex) {
1✔
1827
            throw new IllegalArgumentException(ex);
1✔
1828
        }
1829
    }
1830

1831
    public static List<String> selectTokens(
1832
            final Map<String, Object> object, final String expression) {
1833
        final String xml = toXml(object);
1✔
1834
        try {
1835
            final XPath xPath = XPathFactory.newInstance().newXPath();
1✔
1836
            final org.w3c.dom.Document document = Xml.Document.createDocument(xml);
1✔
1837
            final NodeList nodes =
1✔
1838
                    (NodeList) xPath.compile(expression).evaluate(document, XPathConstants.NODESET);
1✔
1839
            final List<String> result = new ArrayList<>();
1✔
1840
            for (int i = 0; i < nodes.getLength(); i++) {
1✔
1841
                result.add(nodes.item(i).getNodeValue());
1✔
1842
            }
1843
            return result;
1✔
1844
        } catch (Exception ex) {
1✔
1845
            throw new IllegalArgumentException(ex);
1✔
1846
        }
1847
    }
1848

1849
    public static <T> T set(final Map<String, Object> object, final String path, Object value) {
1850
        return set(object, stringToPath(path), value);
1✔
1851
    }
1852

1853
    public static <T> T set(
1854
            final Map<String, Object> object, final List<String> paths, Object value) {
1855
        return baseGetOrSetOrRemove(object, paths, value, OperationType.SET);
1✔
1856
    }
1857

1858
    public static <T> T update(final Map<String, Object> object, final String path, Object value) {
1859
        return update(object, stringToPath(path), value);
1✔
1860
    }
1861

1862
    public static <T> T update(
1863
            final Map<String, Object> object, final List<String> paths, Object value) {
1864
        return baseGetOrSetOrRemove(object, paths, value, OperationType.UPDATE);
1✔
1865
    }
1866

1867
    public static <T> T remove(final Map<String, Object> object, final String path) {
1868
        return remove(object, stringToPath(path));
1✔
1869
    }
1870

1871
    public static <T> T remove(final Map<String, Object> object, final List<String> paths) {
1872
        return baseGetOrSetOrRemove(object, paths, null, OperationType.REMOVE);
1✔
1873
    }
1874

1875
    public static Map<String, Object> rename(
1876
            final Map<String, Object> map, final String oldKey, final String newKey) {
1877
        Map<String, Object> outMap = new LinkedHashMap<>();
1✔
1878
        for (Map.Entry<String, Object> entry : map.entrySet()) {
1✔
1879
            if (entry.getKey().equals(oldKey)) {
1✔
1880
                outMap.put(newKey, makeObjectForRename(entry.getValue(), oldKey, newKey));
1✔
1881
            } else {
1882
                outMap.put(entry.getKey(), makeObjectForRename(entry.getValue(), oldKey, newKey));
1✔
1883
            }
1884
        }
1✔
1885
        return outMap;
1✔
1886
    }
1887

1888
    @SuppressWarnings("unchecked")
1889
    private static Object makeObjectForRename(
1890
            Object value, final String oldKey, final String newKey) {
1891
        final Object result;
1892
        if (value instanceof List) {
1✔
1893
            List<Object> values = new ArrayList<>();
1✔
1894
            for (Object item : (List) value) {
1✔
1895
                values.add(
1✔
1896
                        item instanceof Map
1✔
1897
                                ? rename((Map<String, Object>) item, oldKey, newKey)
1✔
1898
                                : item);
1✔
1899
            }
1✔
1900
            result = values;
1✔
1901
        } else if (value instanceof Map) {
1✔
1902
            result = rename((Map<String, Object>) value, oldKey, newKey);
1✔
1903
        } else {
1904
            result = value;
1✔
1905
        }
1906
        return result;
1✔
1907
    }
1908

1909
    public static Map<String, Object> setValue(
1910
            final Map<String, Object> map, final String key, final Object newValue) {
1911
        return setValue(map, key, (key1, value) -> newValue);
1✔
1912
    }
1913

1914
    public static Map<String, Object> setValue(
1915
            final Map<String, Object> map,
1916
            final String key,
1917
            final BiFunction<String, Object, Object> newValue) {
1918
        Map<String, Object> outMap = new LinkedHashMap<>();
1✔
1919
        for (Map.Entry<String, Object> entry : map.entrySet()) {
1✔
1920
            if (entry.getKey().equals(key)) {
1✔
1921
                outMap.put(
1✔
1922
                        key,
1923
                        makeObjectForSetValue(
1✔
1924
                                newValue.apply(key, entry.getValue()), key, newValue));
1✔
1925
            } else {
1926
                outMap.put(entry.getKey(), makeObjectForSetValue(entry.getValue(), key, newValue));
1✔
1927
            }
1928
        }
1✔
1929
        return outMap;
1✔
1930
    }
1931

1932
    @SuppressWarnings("unchecked")
1933
    private static Object makeObjectForSetValue(
1934
            Object value, final String key, final BiFunction<String, Object, Object> newValue) {
1935
        final Object result;
1936
        if (value instanceof List) {
1✔
1937
            List<Object> values = new ArrayList<>();
1✔
1938
            for (Object item : (List) value) {
1✔
1939
                values.add(
1✔
1940
                        item instanceof Map
1✔
1941
                                ? setValue((Map<String, Object>) item, key, newValue)
1✔
1942
                                : item);
1✔
1943
            }
1✔
1944
            result = values;
1✔
1945
        } else if (value instanceof Map) {
1✔
1946
            result = setValue((Map<String, Object>) value, key, newValue);
1✔
1947
        } else {
1948
            result = value;
1✔
1949
        }
1950
        return result;
1✔
1951
    }
1952

1953
    public static Map<String, Object> update(
1954
            final Map<String, Object> map1, final Map<String, Object> map2) {
1955
        Map<String, Object> outMap = new LinkedHashMap<>();
1✔
1956
        for (Map.Entry<String, Object> entry : map1.entrySet()) {
1✔
1957
            String key = entry.getKey();
1✔
1958
            Object value2 = entry.getValue();
1✔
1959
            if (map2.containsKey(key)) {
1✔
1960
                createKey(map2, key, value2, outMap);
1✔
1961
            } else {
1962
                outMap.put(key, value2);
1✔
1963
            }
1964
        }
1✔
1965
        for (Map.Entry<String, Object> entry : map2.entrySet()) {
1✔
1966
            String key = entry.getKey();
1✔
1967
            Object value2 = entry.getValue();
1✔
1968
            if (map1.containsKey(key)) {
1✔
1969
                createKey(map1, key, value2, outMap);
1✔
1970
            } else {
1971
                outMap.put(key, value2);
1✔
1972
            }
1973
        }
1✔
1974
        return outMap;
1✔
1975
    }
1976

1977
    @SuppressWarnings("unchecked")
1978
    private static void createKey(
1979
            final Map<String, Object> map, String key, Object value2, Map<String, Object> outMap) {
1980
        Object value1 = map.get(key);
1✔
1981
        if (value1 instanceof Map && value2 instanceof Map) {
1✔
1982
            outMap.put(key, update((Map<String, Object>) value1, (Map<String, Object>) value2));
1✔
1983
        } else if (value1 instanceof List && value2 instanceof List) {
1✔
1984
            outMap.put(key, merge((List<Object>) value1, (List<Object>) value2));
1✔
1985
        } else if (value1 instanceof List) {
1✔
1986
            outMap.put(key, merge((List<Object>) value1, newArrayList(value2)));
1✔
1987
        } else if (value2 instanceof List) {
1✔
1988
            outMap.put(key, merge(newArrayList(value1), (List<Object>) value2));
1✔
1989
        } else {
1990
            outMap.put(key, value2);
1✔
1991
        }
1992
    }
1✔
1993

1994
    public static List<Object> merge(List<Object> list1, List<Object> list2) {
1995
        List<Object> outList1 = newArrayList(list1);
1✔
1996
        List<Object> outList2 = newArrayList(list2);
1✔
1997
        outList2.removeAll(list1);
1✔
1998
        outList1.addAll(outList2);
1✔
1999
        return outList1;
1✔
2000
    }
2001

2002
    public static class FetchResponse {
2003
        private final boolean ok;
2004
        private final int status;
2005
        private final Map<String, List<String>> headerFields;
2006
        private final java.io.ByteArrayOutputStream stream;
2007

2008
        public FetchResponse(
2009
                final boolean ok,
2010
                final int status,
2011
                final Map<String, List<String>> headerFields,
2012
                final java.io.ByteArrayOutputStream stream) {
1✔
2013
            this.ok = ok;
1✔
2014
            this.status = status;
1✔
2015
            this.stream = stream;
1✔
2016
            this.headerFields = headerFields;
1✔
2017
        }
1✔
2018

2019
        public boolean isOk() {
2020
            return ok;
1✔
2021
        }
2022

2023
        public int getStatus() {
2024
            return status;
1✔
2025
        }
2026

2027
        public Map<String, List<String>> getHeaderFields() {
2028
            return headerFields;
1✔
2029
        }
2030

2031
        public byte[] blob() {
2032
            return stream.toByteArray();
1✔
2033
        }
2034

2035
        public String text() {
2036
            return stream.toString(StandardCharsets.UTF_8);
1✔
2037
        }
2038

2039
        public Object json() {
2040
            return Json.fromJson(text());
1✔
2041
        }
2042

2043
        public Map<String, Object> jsonMap() {
2044
            return fromJsonMap(text());
1✔
2045
        }
2046

2047
        public Object xml() {
2048
            return Xml.fromXml(text());
1✔
2049
        }
2050

2051
        public Map<String, Object> xmlMap() {
2052
            return fromXmlMap(text());
1✔
2053
        }
2054
    }
2055

2056
    public static long downloadUrl(final String url, final String fileName)
2057
            throws IOException, URISyntaxException {
2058
        final URL website = new URI(url).toURL();
1✔
2059
        try (ReadableByteChannel rbc = Channels.newChannel(website.openStream());
1✔
2060
                final FileOutputStream fos = new FileOutputStream(fileName)) {
1✔
2061
            return fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
1✔
2062
        }
2063
    }
2064

2065
    public static void decompressGzip(final String sourceFileName, final String targetFileName)
2066
            throws IOException {
2067
        try (GZIPInputStream gis = new GZIPInputStream(new FileInputStream(sourceFileName))) {
1✔
2068
            Files.copy(gis, Paths.get(targetFileName));
1✔
2069
        }
2070
    }
1✔
2071

2072
    public static FetchResponse fetch(final String url) {
2073
        return fetch(url, null, null, DEFAULT_HEADER_FIELDS, null, null);
1✔
2074
    }
2075

2076
    public static FetchResponse fetch(
2077
            final String url, final Integer connectTimeout, final Integer readTimeout) {
2078
        return fetch(url, null, null, DEFAULT_HEADER_FIELDS, connectTimeout, readTimeout);
1✔
2079
    }
2080

2081
    public static FetchResponse fetch(
2082
            final String url,
2083
            final Integer connectTimeout,
2084
            final Integer readTimeout,
2085
            final Integer retryCount,
2086
            final Integer timeBetweenRetry) {
2087
        return Fetch.fetch(
1✔
2088
                url,
2089
                null,
2090
                null,
2091
                DEFAULT_HEADER_FIELDS,
2092
                connectTimeout,
2093
                readTimeout,
2094
                retryCount,
2095
                timeBetweenRetry);
2096
    }
2097

2098
    public static FetchResponse fetch(final String url, final String method, final String body) {
2099
        return fetch(url, method, body, DEFAULT_HEADER_FIELDS, null, null);
1✔
2100
    }
2101

2102
    public static class BaseHttpSslSocketFactory extends javax.net.ssl.SSLSocketFactory {
2103
        private javax.net.ssl.SSLContext getSslContext() {
2104
            return createEasySslContext();
2105
        }
2106

2107
        @Override
2108
        public java.net.Socket createSocket(
2109
                java.net.InetAddress arg0, int arg1, java.net.InetAddress arg2, int arg3)
2110
                throws java.io.IOException {
2111
            return getSslContext().getSocketFactory().createSocket(arg0, arg1, arg2, arg3);
2112
        }
2113

2114
        @Override
2115
        public java.net.Socket createSocket(
2116
                String arg0, int arg1, java.net.InetAddress arg2, int arg3)
2117
                throws java.io.IOException {
2118
            return getSslContext().getSocketFactory().createSocket(arg0, arg1, arg2, arg3);
2119
        }
2120

2121
        @Override
2122
        public java.net.Socket createSocket(java.net.InetAddress arg0, int arg1)
2123
                throws java.io.IOException {
2124
            return getSslContext().getSocketFactory().createSocket(arg0, arg1);
2125
        }
2126

2127
        @Override
2128
        public java.net.Socket createSocket(String arg0, int arg1) throws java.io.IOException {
2129
            return getSslContext().getSocketFactory().createSocket(arg0, arg1);
2130
        }
2131

2132
        @Override
2133
        public String[] getSupportedCipherSuites() {
2134
            return new String[] {};
2135
        }
2136

2137
        @Override
2138
        public String[] getDefaultCipherSuites() {
2139
            return new String[] {};
2140
        }
2141

2142
        @Override
2143
        public java.net.Socket createSocket(
2144
                java.net.Socket arg0, String arg1, int arg2, boolean arg3)
2145
                throws java.io.IOException {
2146
            return getSslContext().getSocketFactory().createSocket(arg0, arg1, arg2, arg3);
2147
        }
2148

2149
        private javax.net.ssl.SSLContext createEasySslContext() {
2150
            try {
2151
                javax.net.ssl.SSLContext context = javax.net.ssl.SSLContext.getInstance("SSL");
2152
                context.init(
2153
                        null, new javax.net.ssl.TrustManager[] {MyX509TrustManager.manger}, null);
2154
                return context;
2155
            } catch (Exception ex) {
2156
                throw new UnsupportedOperationException(ex);
2157
            }
2158
        }
2159

2160
        public static class MyX509TrustManager implements javax.net.ssl.X509TrustManager {
2161

2162
            static MyX509TrustManager manger = new MyX509TrustManager();
2163

2164
            public MyX509TrustManager() {
2165
                // ignore MyX509TrustManager
2166
            }
2167

2168
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
2169
                return new java.security.cert.X509Certificate[] {};
2170
            }
2171

2172
            public void checkClientTrusted(
2173
                    java.security.cert.X509Certificate[] chain, String authType) {
2174
                // ignore checkClientTrusted
2175
            }
2176

2177
            public void checkServerTrusted(
2178
                    java.security.cert.X509Certificate[] chain, String authType) {
2179
                // ignore checkServerTrusted
2180
            }
2181
        }
2182
    }
2183

2184
    public static void setupConnection(
2185
            final java.net.HttpURLConnection connection,
2186
            final String method,
2187
            final Map<String, List<String>> headerFields,
2188
            final Integer connectTimeout,
2189
            final Integer readTimeout)
2190
            throws java.io.IOException {
2191
        final String localMethod;
2192
        if (SUPPORTED_HTTP_METHODS.contains(method)) {
1✔
2193
            localMethod = method;
1✔
2194
        } else {
2195
            localMethod = "GET";
1✔
2196
        }
2197
        connection.setRequestMethod(localMethod);
1✔
2198
        if (connectTimeout != null) {
1✔
2199
            connection.setConnectTimeout(connectTimeout);
1✔
2200
        }
2201
        if (readTimeout != null) {
1✔
2202
            connection.setReadTimeout(readTimeout);
1✔
2203
        }
2204
        if (connection instanceof javax.net.ssl.HttpsURLConnection) {
1✔
2205
            ((javax.net.ssl.HttpsURLConnection) connection)
1✔
2206
                    .setSSLSocketFactory(new BaseHttpSslSocketFactory());
1✔
2207
        }
2208
        if (headerFields != null) {
1✔
2209
            for (final Map.Entry<String, List<String>> header : headerFields.entrySet()) {
1✔
2210
                connection.setRequestProperty(header.getKey(), join(header.getValue(), ";"));
1✔
2211
            }
1✔
2212
        }
2213
    }
1✔
2214

2215
    public static FetchResponse fetch(
2216
            final String url,
2217
            final String method,
2218
            final String body,
2219
            final Map<String, List<String>> headerFields,
2220
            final Integer connectTimeout,
2221
            final Integer readTimeout) {
2222
        try {
2223
            final java.net.URL localUrl = new java.net.URI(url).toURL();
1✔
2224
            final java.net.HttpURLConnection connection =
1✔
2225
                    (java.net.HttpURLConnection) localUrl.openConnection();
1✔
2226
            setupConnection(connection, method, headerFields, connectTimeout, readTimeout);
1✔
2227
            if (body != null) {
1✔
2228
                connection.setDoOutput(true);
1✔
2229
                final java.io.DataOutputStream outputStream =
1✔
2230
                        new java.io.DataOutputStream(connection.getOutputStream());
1✔
2231
                outputStream.write(body.getBytes(StandardCharsets.UTF_8));
1✔
2232
                outputStream.close();
1✔
2233
            }
2234
            final int responseCode = connection.getResponseCode();
1✔
2235
            final java.io.InputStream inputStream;
2236
            if (responseCode < RESPONSE_CODE_400) {
1✔
2237
                inputStream = connection.getInputStream();
1✔
2238
            } else {
2239
                inputStream = connection.getErrorStream();
1✔
2240
            }
2241
            final java.io.ByteArrayOutputStream result = new java.io.ByteArrayOutputStream();
1✔
2242
            final byte[] buffer = new byte[BUFFER_LENGTH_1024];
1✔
2243
            int length;
2244
            while ((length = inputStream.read(buffer)) != -1) {
1✔
2245
                result.write(buffer, 0, length);
1✔
2246
            }
2247
            inputStream.close();
1✔
2248
            return new FetchResponse(
1✔
2249
                    responseCode < RESPONSE_CODE_400,
2250
                    responseCode,
2251
                    connection.getHeaderFields(),
1✔
2252
                    result);
2253
        } catch (java.io.IOException | java.net.URISyntaxException ex) {
1✔
2254
            throw new UnsupportedOperationException(ex);
1✔
2255
        }
2256
    }
2257

2258
    public static class Fetch {
2259
        private Fetch() {}
2260

2261
        @SuppressWarnings("java:S107")
2262
        public static FetchResponse fetch(
2263
                final String url,
2264
                final String method,
2265
                final String body,
2266
                final Map<String, List<String>> headerFields,
2267
                final Integer connectTimeout,
2268
                final Integer readTimeout,
2269
                final Integer retryCount,
2270
                final Integer timeBetweenRetry) {
2271
            if (nonNull(retryCount)
2272
                    && retryCount > 0
2273
                    && retryCount <= 10
2274
                    && nonNull(timeBetweenRetry)
2275
                    && timeBetweenRetry > 0) {
2276
                int localRetryCount = 0;
2277
                UnsupportedOperationException saveException;
2278
                do {
2279
                    try {
2280
                        final FetchResponse fetchResponse =
2281
                                U.fetch(
2282
                                        url,
2283
                                        method,
2284
                                        body,
2285
                                        headerFields,
2286
                                        connectTimeout,
2287
                                        readTimeout);
2288
                        if (fetchResponse.getStatus() == 429) {
2289
                            saveException = new UnsupportedOperationException("Too Many Requests");
2290
                        } else {
2291
                            return fetchResponse;
2292
                        }
2293
                    } catch (UnsupportedOperationException ex) {
2294
                        saveException = ex;
2295
                    }
2296
                    localRetryCount += 1;
2297
                    try {
2298
                        java.util.concurrent.TimeUnit.MILLISECONDS.sleep(timeBetweenRetry);
2299
                    } catch (InterruptedException ex) {
2300
                        saveException = new UnsupportedOperationException(ex);
2301
                        Thread.currentThread().interrupt();
2302
                    }
2303
                } while (localRetryCount <= retryCount);
2304
                throw saveException;
2305
            }
2306
            return U.fetch(url, method, body, headerFields, connectTimeout, readTimeout);
2307
        }
2308
    }
2309

2310
    public static List<String> explode(final String input) {
2311
        List<String> result = new ArrayList<>();
1✔
2312
        if (isNull(input)) {
1✔
2313
            return result;
1✔
2314
        }
2315
        for (char character : input.toCharArray()) {
1✔
2316
            result.add(String.valueOf(character));
1✔
2317
        }
2318
        return result;
1✔
2319
    }
2320

2321
    public static String implode(final String[] input) {
2322
        StringBuilder builder = new StringBuilder();
1✔
2323
        for (String character : input) {
1✔
2324
            if (nonNull(character)) {
1✔
2325
                builder.append(character);
1✔
2326
            }
2327
        }
2328
        return builder.toString();
1✔
2329
    }
2330

2331
    public static String implode(final Iterable<String> input) {
2332
        StringBuilder builder = new StringBuilder();
1✔
2333
        for (String character : input) {
1✔
2334
            if (nonNull(character)) {
1✔
2335
                builder.append(character);
1✔
2336
            }
2337
        }
1✔
2338
        return builder.toString();
1✔
2339
    }
2340

2341
    public String camelCase() {
2342
        return camelCase(getString().get());
1✔
2343
    }
2344

2345
    public String lowerFirst() {
2346
        return lowerFirst(getString().get());
1✔
2347
    }
2348

2349
    public String upperFirst() {
2350
        return upperFirst(getString().get());
1✔
2351
    }
2352

2353
    public String capitalize() {
2354
        return capitalize(getString().get());
1✔
2355
    }
2356

2357
    public String deburr() {
2358
        return deburr(getString().get());
1✔
2359
    }
2360

2361
    public boolean endsWith(final String target) {
2362
        return endsWith(getString().get(), target);
1✔
2363
    }
2364

2365
    public boolean endsWith(final String target, final Integer position) {
2366
        return endsWith(getString().get(), target, position);
1✔
2367
    }
2368

2369
    public String kebabCase() {
2370
        return kebabCase(getString().get());
1✔
2371
    }
2372

2373
    public String repeat(final int length) {
2374
        return repeat(getString().get(), length);
1✔
2375
    }
2376

2377
    public String pad(final int length) {
2378
        return pad(getString().get(), length);
1✔
2379
    }
2380

2381
    public String pad(final int length, final String chars) {
2382
        return pad(getString().get(), length, chars);
1✔
2383
    }
2384

2385
    public String padStart(final int length) {
2386
        return padStart(getString().get(), length);
1✔
2387
    }
2388

2389
    public String padStart(final int length, final String chars) {
2390
        return padStart(getString().get(), length, chars);
1✔
2391
    }
2392

2393
    public String padEnd(final int length) {
2394
        return padEnd(getString().get(), length);
1✔
2395
    }
2396

2397
    public String padEnd(final int length, final String chars) {
2398
        return padEnd(getString().get(), length, chars);
1✔
2399
    }
2400

2401
    public String snakeCase() {
2402
        return snakeCase(getString().get());
1✔
2403
    }
2404

2405
    public String startCase() {
2406
        return startCase(getString().get());
1✔
2407
    }
2408

2409
    public boolean startsWith(final String target) {
2410
        return startsWith(getString().get(), target);
1✔
2411
    }
2412

2413
    public boolean startsWith(final String target, final Integer position) {
2414
        return startsWith(getString().get(), target, position);
1✔
2415
    }
2416

2417
    public String trim() {
2418
        return trim(getString().get());
1✔
2419
    }
2420

2421
    public String trimWith(final String chars) {
2422
        return trim(getString().get(), chars);
1✔
2423
    }
2424

2425
    public String trimStart() {
2426
        return trimStart(getString().get());
1✔
2427
    }
2428

2429
    public String trimStartWith(final String chars) {
2430
        return trimStart(getString().get(), chars);
1✔
2431
    }
2432

2433
    public String trimEnd() {
2434
        return trimEnd(getString().get());
1✔
2435
    }
2436

2437
    public String trimEndWith(final String chars) {
2438
        return trimEnd(getString().get(), chars);
1✔
2439
    }
2440

2441
    public String trunc() {
2442
        return trunc(getString().get());
1✔
2443
    }
2444

2445
    public String trunc(final int length) {
2446
        return trunc(getString().get(), length);
1✔
2447
    }
2448

2449
    public String uncapitalize() {
2450
        return uncapitalize(getString().get());
1✔
2451
    }
2452

2453
    public List<String> words() {
2454
        return words(getString().get());
1✔
2455
    }
2456

2457
    public static class LruCache<K, V> {
2458
        private static final boolean SORT_BY_ACCESS = true;
2459
        private static final float LOAD_FACTOR = 0.75F;
2460
        private final Map<K, V> lruCacheMap;
2461
        private final int capacity;
2462

2463
        public LruCache(int capacity) {
1✔
2464
            this.capacity = capacity;
1✔
2465
            this.lruCacheMap = new LinkedHashMap<>(capacity, LOAD_FACTOR, SORT_BY_ACCESS);
1✔
2466
        }
1✔
2467

2468
        public V get(K key) {
2469
            return lruCacheMap.get(key);
1✔
2470
        }
2471

2472
        public void put(K key, V value) {
2473
            if (lruCacheMap.containsKey(key)) {
1✔
2474
                lruCacheMap.remove(key);
1✔
2475
            } else if (lruCacheMap.size() >= capacity) {
1✔
2476
                lruCacheMap.remove(lruCacheMap.keySet().iterator().next());
1✔
2477
            }
2478
            lruCacheMap.put(key, value);
1✔
2479
        }
1✔
2480
    }
2481

2482
    public static <K, V> LruCache<K, V> createLruCache(final int capacity) {
2483
        return new LruCache<>(capacity);
1✔
2484
    }
2485

2486
    public static <T> List<List<T>> createPermutationWithRepetition(
2487
            final List<T> list, final int permutationLength) {
2488
        final long resultSize = (long) Math.pow(list.size(), permutationLength);
1✔
2489
        final List<List<T>> result = new ArrayList<>((int) resultSize);
1✔
2490
        final int[] bitVector = new int[permutationLength];
1✔
2491
        for (int index = 0; index < resultSize; index += 1) {
1✔
2492
            List<T> result2 = new ArrayList<>(permutationLength);
1✔
2493
            for (int index2 = 0; index2 < permutationLength; index2 += 1) {
1✔
2494
                result2.add(list.get(bitVector[index2]));
1✔
2495
            }
2496
            int index3 = 0;
1✔
2497
            while (index3 < permutationLength && bitVector[index3] == list.size() - 1) {
1✔
2498
                bitVector[index3] = 0;
1✔
2499
                index3 += 1;
1✔
2500
            }
2501
            if (index3 < permutationLength) {
1✔
2502
                bitVector[index3] += 1;
1✔
2503
            }
2504
            result.add(result2);
1✔
2505
        }
2506
        return result;
1✔
2507
    }
2508

2509
    public List<List<T>> createPermutationWithRepetition(final int permutationLength) {
2510
        return createPermutationWithRepetition((List<T>) value(), permutationLength);
1✔
2511
    }
2512

2513
    protected static <T> List<T> newArrayList(final Iterable<T> iterable) {
2514
        return Underscore.newArrayList(iterable);
1✔
2515
    }
2516

2517
    public static <T> String join(final Iterable<T> iterable, final String separator) {
2518
        return Underscore.join(iterable, separator);
1✔
2519
    }
2520

2521
    public static <T> String joinToString(
2522
            final Iterable<T> iterable,
2523
            final String separator,
2524
            final String prefix,
2525
            final String postfix,
2526
            final int limit,
2527
            final String truncated,
2528
            final Function<T, String> transform) {
2529
        return Underscore.joinToString(
1✔
2530
                iterable, separator, prefix, postfix, limit, truncated, transform);
2531
    }
2532

2533
    public static String toJson(Collection collection) {
2534
        return Json.toJson(collection);
1✔
2535
    }
2536

2537
    public static String toJson(Map map) {
2538
        return Json.toJson(map);
1✔
2539
    }
2540

2541
    public String toJson() {
2542
        return Json.toJson((Collection) getIterable());
1✔
2543
    }
2544

2545
    @SuppressWarnings("unchecked")
2546
    public static <T> T fromXml(final String xml) {
2547
        return (T) Xml.fromXml(xml);
1✔
2548
    }
2549

2550
    public static Map<String, Object> fromXmlMap(final String xml) {
2551
        return fromXmlMap(xml, Xml.FromType.FOR_CONVERT);
1✔
2552
    }
2553

2554
    public static Map<String, Object> fromXmlMap(final String xml, final Xml.FromType fromType) {
2555
        final Object object = Xml.fromXml(xml, fromType);
1✔
2556
        return getStringObjectMap(object);
1✔
2557
    }
2558

2559
    @SuppressWarnings("unchecked")
2560
    public static <T> T fromXml(final String xml, final Xml.FromType fromType) {
2561
        return (T) Xml.fromXml(xml, fromType);
1✔
2562
    }
2563

2564
    @SuppressWarnings("unchecked")
2565
    public static <T> T fromXmlMakeArrays(final String xml) {
2566
        return (T) Xml.fromXmlMakeArrays(xml);
1✔
2567
    }
2568

2569
    @SuppressWarnings("unchecked")
2570
    public static <T> T fromXmlWithoutNamespaces(final String xml) {
2571
        return (T) Xml.fromXmlWithoutNamespaces(xml);
1✔
2572
    }
2573

2574
    public static Map<String, Object> fromXmlWithoutNamespacesMap(final String xml) {
2575
        final Object object = Xml.fromXmlWithoutNamespaces(xml);
1✔
2576
        return getStringObjectMap(object);
1✔
2577
    }
2578

2579
    @SuppressWarnings("unchecked")
2580
    public static <T> T fromXmlWithoutAttributes(final String xml) {
2581
        return (T) Xml.fromXmlWithoutAttributes(xml);
1✔
2582
    }
2583

2584
    @SuppressWarnings("unchecked")
2585
    public static <T> T fromXmlWithoutNamespacesAndAttributes(final String xml) {
2586
        return (T) Xml.fromXmlWithoutNamespacesAndAttributes(xml);
1✔
2587
    }
2588

2589
    public static String toXml(Collection collection) {
2590
        return Xml.toXml(collection);
1✔
2591
    }
2592

2593
    public static String toXml(Map map) {
2594
        return Xml.toXml(map);
1✔
2595
    }
2596

2597
    @SuppressWarnings("unchecked")
2598
    public static <T> T fromJson(String string) {
2599
        return (T) Json.fromJson(string);
1✔
2600
    }
2601

2602
    public Object fromJson() {
2603
        return Json.fromJson(getString().get());
1✔
2604
    }
2605

2606
    public static Map<String, Object> fromJsonMap(final String string) {
2607
        final Object object = Json.fromJson(string);
1✔
2608
        return getStringObjectMap(object);
1✔
2609
    }
2610

2611
    public static Map<String, Object> fromJsonMap(final String string, final int maxDepth) {
2612
        final Object object = Json.fromJson(string, maxDepth);
1✔
2613
        return getStringObjectMap(object);
1✔
2614
    }
2615

2616
    @SuppressWarnings("unchecked")
2617
    private static Map<String, Object> getStringObjectMap(Object object) {
2618
        final Map<String, Object> result;
2619
        if (object instanceof Map) {
1✔
2620
            result = (Map<String, Object>) object;
1✔
2621
        } else {
2622
            result = new LinkedHashMap<>();
1✔
2623
            result.put("value", object);
1✔
2624
        }
2625
        return result;
1✔
2626
    }
2627

2628
    public String toXml() {
2629
        return Xml.toXml((Collection) getIterable());
1✔
2630
    }
2631

2632
    public Object fromXml() {
2633
        return Xml.fromXml(getString().get());
1✔
2634
    }
2635

2636
    @SuppressWarnings("unchecked")
2637
    public static String jsonToXml(
2638
            String json,
2639
            Xml.XmlStringBuilder.Step identStep,
2640
            JsonToXmlMode mode,
2641
            String newRootName) {
2642
        Object object = Json.fromJson(json);
1✔
2643
        final String result;
2644
        if (object instanceof Map) {
1✔
2645
            if (mode == JsonToXmlMode.FORCE_ATTRIBUTE_USAGE) {
1✔
2646
                result = Xml.toXml(forceAttributeUsage((Map) object), identStep, newRootName);
1✔
2647
            } else if (mode == JsonToXmlMode.DEFINE_ROOT_NAME) {
1✔
2648
                result = Xml.toXml((Map) object, identStep, newRootName);
1✔
2649
            } else if (mode == JsonToXmlMode.REPLACE_NULL_WITH_EMPTY_VALUE) {
1✔
2650
                result = Xml.toXml(replaceNullWithEmptyValue((Map) object), identStep, newRootName);
1✔
2651
            } else if (mode == JsonToXmlMode.REPLACE_EMPTY_STRING_WITH_EMPTY_VALUE) {
1✔
2652
                result =
1✔
2653
                        Xml.toXml(
1✔
2654
                                replaceEmptyStringWithEmptyValue((Map) object),
1✔
2655
                                identStep,
2656
                                newRootName);
2657
            } else if (mode == JsonToXmlMode.ADD_ROOT
1✔
2658
                    && !Xml.XmlValue.getMapKey(object).equals(ROOT)) {
1✔
2659
                final Map<String, Object> map = new LinkedHashMap<>();
1✔
2660
                map.put(newRootName, object);
1✔
2661
                result = Xml.toXml(map, identStep);
1✔
2662
            } else if (mode == JsonToXmlMode.REMOVE_ARRAY_ATTRIBUTE) {
1✔
2663
                result = Xml.toXml((Map) object, identStep, newRootName, Xml.ArrayTrue.SKIP);
1✔
2664
            } else if (mode == JsonToXmlMode.REMOVE_ATTRIBUTES) {
1✔
2665
                result =
1✔
2666
                        Xml.toXml(
1✔
2667
                                replaceNumberAndBooleanWithString((Map) object),
1✔
2668
                                identStep,
2669
                                newRootName,
2670
                                Xml.ArrayTrue.SKIP);
2671
            } else {
2672
                result = Xml.toXml((Map) object, identStep);
1✔
2673
            }
2674
            return result;
1✔
2675
        }
2676
        return Xml.toXml((List) object, identStep);
1✔
2677
    }
2678

2679
    public static String jsonToXml(String json, Xml.XmlStringBuilder.Step identStep) {
2680
        return jsonToXml(json, identStep, null, ROOT);
1✔
2681
    }
2682

2683
    public static String jsonToXml(String json, JsonToXmlMode mode) {
2684
        return jsonToXml(json, Xml.XmlStringBuilder.Step.TWO_SPACES, mode, ROOT);
1✔
2685
    }
2686

2687
    public static String jsonToXml(String json, JsonToXmlMode mode, String newRootName) {
2688
        return jsonToXml(json, Xml.XmlStringBuilder.Step.TWO_SPACES, mode, newRootName);
1✔
2689
    }
2690

2691
    public static String jsonToXml(String json, String newRootName) {
2692
        return jsonToXml(
1✔
2693
                json,
2694
                Xml.XmlStringBuilder.Step.TWO_SPACES,
2695
                JsonToXmlMode.DEFINE_ROOT_NAME,
2696
                newRootName);
2697
    }
2698

2699
    public static String jsonToXml(String json) {
2700
        return jsonToXml(json, Xml.XmlStringBuilder.Step.TWO_SPACES, null, null);
1✔
2701
    }
2702

2703
    @SuppressWarnings("unchecked")
2704
    public static String jsonToXmlMinimum(String json, Xml.XmlStringBuilder.Step identStep) {
2705
        Object object = Json.fromJson(json);
1✔
2706
        if (object instanceof Map) {
1✔
2707
            ((Map<String, Object>) object).put(OMIT_XML_DECL, YES);
1✔
2708
            return Xml.toXml(replaceNumberAndBooleanWithString((Map) object), identStep);
1✔
2709
        }
2710
        return Xml.toXmlWithoutRoot((List) object, identStep);
1✔
2711
    }
2712

2713
    public static String jsonToXmlMinimum(String json) {
2714
        return jsonToXmlMinimum(json, Xml.XmlStringBuilder.Step.TWO_SPACES);
1✔
2715
    }
2716

2717
    @SuppressWarnings("unchecked")
2718
    public static String xmlToJson(
2719
            String xml, Json.JsonStringBuilder.Step identStep, XmlToJsonMode mode) {
2720
        Object object = Xml.fromXml(xml);
1✔
2721
        final String result;
2722
        if (object instanceof Map) {
1✔
2723
            if (mode == XmlToJsonMode.REPLACE_SELF_CLOSING_WITH_NULL) {
1✔
2724
                result = Json.toJson(replaceSelfClosingWithNull((Map) object), identStep);
1✔
2725
            } else if (mode == XmlToJsonMode.REPLACE_SELF_CLOSING_WITH_STRING) {
1✔
2726
                result = Json.toJson(replaceSelfClosingWithEmpty((Map) object), identStep);
1✔
2727
            } else if (mode == XmlToJsonMode.REPLACE_EMPTY_VALUE_WITH_NULL) {
1✔
2728
                result = Json.toJson(replaceEmptyValueWithNull((Map) object), identStep);
1✔
2729
            } else if (mode == XmlToJsonMode.REPLACE_MINUS_WITH_AT) {
1✔
2730
                result = Json.toJson(replaceMinusWithAt((Map) object), identStep);
1✔
2731
            } else if (mode == XmlToJsonMode.REPLACE_EMPTY_TAG_WITH_NULL_AND_MINUS_WITH_AT) {
1✔
2732
                result =
1✔
2733
                        Json.toJson(
1✔
2734
                                replaceMinusWithAt(
1✔
2735
                                        replaceEmptyValueWithNull(
1✔
2736
                                                replaceSelfClosingWithNull((Map) object))),
1✔
2737
                                identStep);
2738
            } else if (mode == XmlToJsonMode.REPLACE_EMPTY_TAG_WITH_NULL) {
1✔
2739
                result =
1✔
2740
                        Json.toJson(
1✔
2741
                                replaceEmptyValueWithNull(replaceSelfClosingWithNull((Map) object)),
1✔
2742
                                identStep);
2743
            } else if (mode == XmlToJsonMode.REPLACE_EMPTY_TAG_WITH_STRING) {
1✔
2744
                result =
1✔
2745
                        Json.toJson(
1✔
2746
                                (Map<String, Object>)
2747
                                        replaceEmptyValueWithEmptyString(
1✔
2748
                                                replaceSelfClosingWithEmpty((Map) object)),
1✔
2749
                                identStep);
2750
            } else if (mode == XmlToJsonMode.REMOVE_FIRST_LEVEL) {
1✔
2751
                result = Json.toJson(replaceFirstLevel((Map) object), identStep);
1✔
2752
            } else if (mode == XmlToJsonMode.WITHOUT_NAMESPACES) {
1✔
2753
                result = Json.toJson((Map) Xml.fromXmlWithoutNamespaces(xml), identStep);
1✔
2754
            } else {
2755
                result = Json.toJson((Map) object, identStep);
1✔
2756
            }
2757
            return result;
1✔
2758
        }
2759
        return Json.toJson((List) object, identStep);
1✔
2760
    }
2761

2762
    public static String xmlToJson(String xml) {
2763
        return xmlToJson(xml, Json.JsonStringBuilder.Step.TWO_SPACES, null);
1✔
2764
    }
2765

2766
    @SuppressWarnings("unchecked")
2767
    public static String xmlToJsonMinimum(String xml, Json.JsonStringBuilder.Step identStep) {
2768
        Object object = Xml.fromXml(xml);
1✔
2769
        if (object instanceof Map) {
1✔
2770
            ((Map) object).remove(OMIT_XML_DECL);
1✔
2771
            return Json.toJson(replaceSelfClosingWithEmpty((Map) object), identStep);
1✔
2772
        }
2773
        return Json.toJson((List) object, identStep);
1✔
2774
    }
2775

2776
    public static String xmlToJsonMinimum(String xml) {
2777
        return xmlToJsonMinimum(xml, Json.JsonStringBuilder.Step.TWO_SPACES);
1✔
2778
    }
2779

2780
    public static String xmlToJson(String xml, Json.JsonStringBuilder.Step identStep) {
2781
        return xmlToJson(xml, identStep, null);
1✔
2782
    }
2783

2784
    public static String xmlToJson(String xml, XmlToJsonMode mode) {
2785
        return xmlToJson(xml, Json.JsonStringBuilder.Step.TWO_SPACES, mode);
1✔
2786
    }
2787

2788
    public static void fileXmlToJson(
2789
            String xmlFileName, String jsonFileName, Json.JsonStringBuilder.Step identStep)
2790
            throws IOException {
2791
        final byte[] bytes = Files.readAllBytes(Paths.get(xmlFileName));
1✔
2792
        String xmlText = new String(removeBom(bytes), detectEncoding(bytes));
1✔
2793
        Files.write(
1✔
2794
                Paths.get(jsonFileName),
1✔
2795
                formatString(xmlToJson(xmlText, identStep), System.lineSeparator())
1✔
2796
                        .getBytes(StandardCharsets.UTF_8));
1✔
2797
    }
1✔
2798

2799
    public static void fileXmlToJson(String xmlFileName, String jsonFileName) throws IOException {
2800
        fileXmlToJson(xmlFileName, jsonFileName, Json.JsonStringBuilder.Step.TWO_SPACES);
1✔
2801
    }
1✔
2802

2803
    public static void streamXmlToJson(
2804
            InputStream xmlInputStream,
2805
            OutputStream jsonOutputStream,
2806
            Json.JsonStringBuilder.Step indentStep)
2807
            throws IOException {
2808
        byte[] bytes = xmlInputStream.readAllBytes();
1✔
2809
        String encoding = detectEncoding(bytes);
1✔
2810
        String xmlText = new String(removeBom(bytes), encoding);
1✔
2811
        String jsonText = xmlToJson(xmlText, indentStep);
1✔
2812
        String formattedJson = formatString(jsonText, System.lineSeparator());
1✔
2813
        jsonOutputStream.write(formattedJson.getBytes(StandardCharsets.UTF_8));
1✔
2814
    }
1✔
2815

2816
    public static void streamXmlToJson(InputStream xmlInputStream, OutputStream jsonOutputStream)
2817
            throws IOException {
2818
        streamXmlToJson(xmlInputStream, jsonOutputStream, Json.JsonStringBuilder.Step.TWO_SPACES);
1✔
2819
    }
1✔
2820

2821
    public static void fileJsonToXml(
2822
            String jsonFileName, String xmlFileName, Xml.XmlStringBuilder.Step identStep)
2823
            throws IOException {
2824
        final byte[] bytes = Files.readAllBytes(Paths.get(jsonFileName));
1✔
2825
        String jsonText = new String(removeBom(bytes), detectEncoding(bytes));
1✔
2826
        Object result = U.fromJson(jsonText);
1✔
2827
        Path xmlFilePath = Paths.get(xmlFileName);
1✔
2828
        String lineSeparator = System.lineSeparator();
1✔
2829
        if (result instanceof Map) {
1✔
2830
            if (((Map) result).containsKey(ENCODING)) {
1✔
2831
                String encoding = String.valueOf(((Map) result).get(ENCODING));
1✔
2832
                Files.write(
1✔
2833
                        xmlFilePath,
2834
                        formatString(Xml.toXml((Map) result, identStep), lineSeparator)
1✔
2835
                                .getBytes(encoding));
1✔
2836
            } else {
1✔
2837
                Files.write(
1✔
2838
                        xmlFilePath,
2839
                        formatString(Xml.toXml((Map) result, identStep), lineSeparator)
1✔
2840
                                .getBytes(StandardCharsets.UTF_8));
1✔
2841
            }
2842
        } else {
2843
            Files.write(
1✔
2844
                    xmlFilePath,
2845
                    formatString(Xml.toXml((List) result, identStep), lineSeparator)
1✔
2846
                            .getBytes(StandardCharsets.UTF_8));
1✔
2847
        }
2848
    }
1✔
2849

2850
    public static void fileJsonToXml(String jsonFileName, String xmlFileName) throws IOException {
2851
        fileJsonToXml(jsonFileName, xmlFileName, Xml.XmlStringBuilder.Step.TWO_SPACES);
1✔
2852
    }
1✔
2853

2854
    public static void streamJsonToXml(
2855
            InputStream jsonInputStream,
2856
            OutputStream xmlOutputStream,
2857
            Xml.XmlStringBuilder.Step identStep)
2858
            throws IOException {
2859
        byte[] bytes = jsonInputStream.readAllBytes();
1✔
2860
        String jsonText = new String(removeBom(bytes), detectEncoding(bytes));
1✔
2861
        Object jsonObject = U.fromJson(jsonText);
1✔
2862
        String lineSeparator = System.lineSeparator();
1✔
2863
        String xml;
2864
        if (jsonObject instanceof Map) {
1✔
2865
            xml = formatString(Xml.toXml((Map<?, ?>) jsonObject, identStep), lineSeparator);
1✔
2866
            if (((Map) jsonObject).containsKey(ENCODING)) {
1✔
2867
                String encoding = String.valueOf(((Map) jsonObject).get(ENCODING));
1✔
2868
                xmlOutputStream.write(xml.getBytes(encoding));
1✔
2869
            } else {
1✔
2870
                xmlOutputStream.write(xml.getBytes(StandardCharsets.UTF_8));
1✔
2871
            }
2872
        } else {
2873
            xml = formatString(Xml.toXml((List<?>) jsonObject, identStep), lineSeparator);
1✔
2874
            xmlOutputStream.write(xml.getBytes(StandardCharsets.UTF_8));
1✔
2875
        }
2876
    }
1✔
2877

2878
    public static void streamJsonToXml(InputStream jsonInputStream, OutputStream xmlOutputStream)
2879
            throws IOException {
2880
        streamJsonToXml(jsonInputStream, xmlOutputStream, Xml.XmlStringBuilder.Step.TWO_SPACES);
1✔
2881
    }
1✔
2882

2883
    public static byte[] removeBom(byte[] bytes) {
2884
        if ((bytes.length >= 3) && (bytes[0] == -17) && (bytes[1] == -69) && (bytes[2] == -65)) {
1✔
2885
            return Arrays.copyOfRange(bytes, 3, bytes.length);
1✔
2886
        }
2887
        if ((bytes.length >= 2) && (bytes[0] == -1) && (bytes[1] == -2)) {
1✔
2888
            return Arrays.copyOfRange(bytes, 2, bytes.length);
1✔
2889
        }
2890
        if ((bytes.length >= 2) && (bytes[0] == -2) && (bytes[1] == -1)) {
1✔
2891
            return Arrays.copyOfRange(bytes, 2, bytes.length);
1✔
2892
        }
2893
        return bytes;
1✔
2894
    }
2895

2896
    public static String detectEncoding(byte[] buffer) {
2897
        if (buffer.length < 4) {
1✔
2898
            return "UTF8";
1✔
2899
        }
2900
        String encoding = null;
1✔
2901
        int n =
1✔
2902
                ((buffer[0] & 0xFF) << 24)
2903
                        | ((buffer[1] & 0xFF) << 16)
2904
                        | ((buffer[2] & 0xFF) << 8)
2905
                        | (buffer[3] & 0xFF);
2906
        switch (n) {
1✔
2907
            case 0x0000FEFF:
2908
            case 0x0000003C:
2909
                encoding = "UTF_32BE";
1✔
2910
                break;
1✔
2911
            case 0x003C003F:
2912
                encoding = "UnicodeBigUnmarked";
1✔
2913
                break;
1✔
2914
            case 0xFFFE0000:
2915
            case 0x3C000000:
2916
                encoding = "UTF_32LE";
1✔
2917
                break;
1✔
2918
                // <?
2919
            case 0x3C003F00:
2920
                encoding = "UnicodeLittleUnmarked";
1✔
2921
                break;
1✔
2922
                // <?xm
2923
            case 0x3C3F786D:
2924
                encoding = "UTF8";
1✔
2925
                break;
1✔
2926
            default:
2927
                if ((n >>> 8) == 0xEFBBBF) {
1✔
2928
                    encoding = "UTF8";
1✔
2929
                    break;
1✔
2930
                }
2931
                if ((n >>> 24) == 0x3C) {
1✔
2932
                    break;
1✔
2933
                }
2934
                switch (n >>> 16) {
1✔
2935
                    case 0xFFFE:
2936
                        encoding = "UnicodeLittleUnmarked";
1✔
2937
                        break;
1✔
2938
                    case 0xFEFF:
2939
                        encoding = "UnicodeBigUnmarked";
1✔
2940
                        break;
1✔
2941
                    default:
2942
                        break;
2943
                }
2944
        }
2945
        return encoding == null ? "UTF8" : encoding;
1✔
2946
    }
2947

2948
    public static String formatString(String data, String lineSeparator) {
2949
        if ("\n".equals(lineSeparator)) {
1✔
2950
            return data;
1✔
2951
        }
2952
        return data.replace("\n", lineSeparator);
1✔
2953
    }
2954

2955
    public static String xmlOrJsonToJson(String xmlOrJson, Json.JsonStringBuilder.Step identStep) {
2956
        TextType textType = getTextType(xmlOrJson);
1✔
2957
        final String result;
2958
        if (textType == TextType.JSON) {
1✔
2959
            result = getJsonString(identStep, fromJson(xmlOrJson));
1✔
2960
        } else if (textType == TextType.XML) {
1✔
2961
            result = getJsonString(identStep, fromXml(xmlOrJson));
1✔
2962
        } else {
2963
            result = xmlOrJson;
1✔
2964
        }
2965
        return result;
1✔
2966
    }
2967

2968
    public static String xmlOrJsonToJson(String xmlOrJson) {
2969
        return xmlOrJsonToJson(xmlOrJson, Json.JsonStringBuilder.Step.TWO_SPACES);
1✔
2970
    }
2971

2972
    public static String mergeXmlsOrJsonsToJson(
2973
            List<String> xmlsOrJsons, Json.JsonStringBuilder.Step identStep) {
2974
        Map<String, Object> resultJsonMap = new LinkedHashMap<>();
1✔
2975
        for (String xmlOrJsonToJson : xmlsOrJsons) {
1✔
2976
            TextType textType = getTextType(xmlOrJsonToJson);
1✔
2977
            final Map<String, Object> jsonOrXmlMap;
2978
            if (textType == TextType.JSON) {
1✔
2979
                jsonOrXmlMap = fromJsonMap(xmlOrJsonToJson);
1✔
2980
            } else if (textType == TextType.XML) {
1✔
2981
                jsonOrXmlMap = fromXmlMap(xmlOrJsonToJson);
1✔
2982
            } else {
2983
                continue;
2984
            }
2985
            resultJsonMap = U.update(resultJsonMap, jsonOrXmlMap);
1✔
2986
        }
1✔
2987
        return resultJsonMap.isEmpty() ? "" : Json.toJson(resultJsonMap, identStep);
1✔
2988
    }
2989

2990
    public static String mergeXmlsOrJsonsToJson(List<String> xmlsOrJsons) {
2991
        return mergeXmlsOrJsonsToJson(xmlsOrJsons, Json.JsonStringBuilder.Step.TWO_SPACES);
1✔
2992
    }
2993

2994
    public static String mergeXmlsOrJsonsToXml(
2995
            List<String> xmlsOrJsons, Xml.XmlStringBuilder.Step identStep) {
2996
        Map<String, Object> resultXmlMap = new LinkedHashMap<>();
1✔
2997
        for (String xmlOrJsonToXml : xmlsOrJsons) {
1✔
2998
            TextType textType = getTextType(xmlOrJsonToXml);
1✔
2999
            final Map<String, Object> jsonOrXmlMap;
3000
            if (textType == TextType.JSON) {
1✔
3001
                jsonOrXmlMap = fromJsonMap(xmlOrJsonToXml);
1✔
3002
            } else if (textType == TextType.XML) {
1✔
3003
                jsonOrXmlMap = fromXmlMap(xmlOrJsonToXml);
1✔
3004
            } else {
3005
                continue;
3006
            }
3007
            resultXmlMap = U.update(resultXmlMap, jsonOrXmlMap);
1✔
3008
        }
1✔
3009
        return resultXmlMap.isEmpty() ? "" : Xml.toXml(resultXmlMap, identStep);
1✔
3010
    }
3011

3012
    public static String mergeXmlsOrJsonsToXml(List<String> xmlsOrJsons) {
3013
        return mergeXmlsOrJsonsToXml(xmlsOrJsons, Xml.XmlStringBuilder.Step.TWO_SPACES);
1✔
3014
    }
3015

3016
    @SuppressWarnings("unchecked")
3017
    private static String getJsonString(Json.JsonStringBuilder.Step identStep, Object object) {
3018
        final String result;
3019
        if (object instanceof Map) {
1✔
3020
            result = Json.toJson((Map) object, identStep);
1✔
3021
        } else {
3022
            result = Json.toJson((List) object, identStep);
1✔
3023
        }
3024
        return result;
1✔
3025
    }
3026

3027
    public static String xmlOrJsonToXml(String xmlOrJson, Xml.XmlStringBuilder.Step identStep) {
3028
        TextType textType = getTextType(xmlOrJson);
1✔
3029
        final String result;
3030
        if (textType == TextType.JSON) {
1✔
3031
            result = getXmlString(identStep, fromJson(xmlOrJson));
1✔
3032
        } else if (textType == TextType.XML) {
1✔
3033
            result = getXmlString(identStep, fromXml(xmlOrJson));
1✔
3034
        } else {
3035
            result = xmlOrJson;
1✔
3036
        }
3037
        return result;
1✔
3038
    }
3039

3040
    public static String xmlOrJsonToXml(String xmlOrJson) {
3041
        return xmlOrJsonToXml(xmlOrJson, Xml.XmlStringBuilder.Step.TWO_SPACES);
1✔
3042
    }
3043

3044
    @SuppressWarnings("unchecked")
3045
    private static String getXmlString(Xml.XmlStringBuilder.Step identStep, Object object) {
3046
        final String result;
3047
        if (object instanceof Map) {
1✔
3048
            result = Xml.toXml((Map) object, identStep);
1✔
3049
        } else {
3050
            result = Xml.toXml((List) object, identStep);
1✔
3051
        }
3052
        return result;
1✔
3053
    }
3054

3055
    public enum TextType {
1✔
3056
        JSON,
1✔
3057
        XML,
1✔
3058
        OTHER
1✔
3059
    }
3060

3061
    public static TextType getTextType(String text) {
3062
        String trimmed = trim(text);
1✔
3063
        final TextType textType;
3064
        if (trimmed.startsWith("{") && trimmed.endsWith("}")
1✔
3065
                || trimmed.startsWith("[") && trimmed.endsWith("]")) {
1✔
3066
            textType = TextType.JSON;
1✔
3067
        } else if (trimmed.startsWith("<") && trimmed.endsWith(">")) {
1✔
3068
            textType = TextType.XML;
1✔
3069
        } else {
3070
            textType = TextType.OTHER;
1✔
3071
        }
3072
        return textType;
1✔
3073
    }
3074

3075
    public static String formatJsonOrXml(String jsonOrXml, String identStep) {
3076
        TextType textType = getTextType(jsonOrXml);
1✔
3077
        final String result;
3078
        if (textType == TextType.JSON) {
1✔
3079
            result = formatJson(jsonOrXml, Json.JsonStringBuilder.Step.valueOf(identStep));
1✔
3080
        } else if (textType == TextType.XML) {
1✔
3081
            result = formatXml(jsonOrXml, Xml.XmlStringBuilder.Step.valueOf(identStep));
1✔
3082
        } else {
3083
            result = jsonOrXml;
1✔
3084
        }
3085
        return result;
1✔
3086
    }
3087

3088
    public static String formatJsonOrXml(String jsonOrXml) {
3089
        return formatJsonOrXml(jsonOrXml, "TWO_SPACES");
1✔
3090
    }
3091

3092
    public static String formatJson(String json, Json.JsonStringBuilder.Step identStep) {
3093
        return Json.formatJson(json, identStep);
1✔
3094
    }
3095

3096
    public static String formatJson(String json) {
3097
        return Json.formatJson(json);
1✔
3098
    }
3099

3100
    public static String formatXml(String xml, Xml.XmlStringBuilder.Step identStep) {
3101
        return Xml.formatXml(xml, identStep);
1✔
3102
    }
3103

3104
    public static String formatXml(String xml) {
3105
        return Xml.formatXml(xml);
1✔
3106
    }
3107

3108
    public static String changeXmlEncoding(
3109
            String xml, Xml.XmlStringBuilder.Step identStep, String encoding) {
3110
        return Xml.changeXmlEncoding(xml, identStep, encoding);
1✔
3111
    }
3112

3113
    public static String changeXmlEncoding(String xml, String encoding) {
3114
        return Xml.changeXmlEncoding(xml, encoding);
1✔
3115
    }
3116

3117
    public static Map<String, Object> removeMinusesAndConvertNumbers(Map<String, Object> map) {
3118
        Map<String, Object> outMap = new LinkedHashMap<>();
1✔
3119
        for (Map.Entry<String, Object> entry : map.entrySet()) {
1✔
3120
            final String newKey;
3121
            if (entry.getKey().startsWith("-")) {
1✔
3122
                newKey = entry.getKey().substring(1);
1✔
3123
            } else {
3124
                newKey = entry.getKey();
1✔
3125
            }
3126
            if (!entry.getKey().equals(SELF_CLOSING) && !entry.getKey().equals(OMIT_XML_DECL)) {
1✔
3127
                outMap.put(newKey, makeObject(entry.getValue()));
1✔
3128
            }
3129
        }
1✔
3130
        return outMap;
1✔
3131
    }
3132

3133
    @SuppressWarnings("unchecked")
3134
    private static Object makeObject(Object value) {
3135
        final Object result;
3136
        if (value instanceof List) {
1✔
3137
            List<Object> values = new ArrayList<>();
1✔
3138
            for (Object item : (List) value) {
1✔
3139
                values.add(
1✔
3140
                        item instanceof Map
1✔
3141
                                ? removeMinusesAndConvertNumbers((Map<String, Object>) item)
1✔
3142
                                : item);
1✔
3143
            }
1✔
3144
            result = values;
1✔
3145
        } else if (value instanceof Map) {
1✔
3146
            result = removeMinusesAndConvertNumbers((Map) value);
1✔
3147
        } else {
3148
            String stringValue = String.valueOf(value);
1✔
3149
            result = isJsonNumber(stringValue) ? Xml.stringToNumber(stringValue) : value;
1✔
3150
        }
3151
        return result;
1✔
3152
    }
3153

3154
    public static boolean isJsonNumber(final String string) {
3155
        boolean eFound = false;
1✔
3156
        boolean periodValid = true;
1✔
3157
        boolean pmValid = true;
1✔
3158
        boolean numberEncountered = false;
1✔
3159
        for (char ch : string.toCharArray()) {
1✔
3160
            if (pmValid) {
1✔
3161
                pmValid = false;
1✔
3162
                if (ch == '-') {
1✔
3163
                    continue;
1✔
3164
                }
3165
            }
3166
            if (!eFound && (ch == 'e' || ch == 'E')) {
1✔
3167
                eFound = true;
1✔
3168
                periodValid = false;
1✔
3169
                pmValid = true;
1✔
3170
                numberEncountered = false;
1✔
3171
                continue;
1✔
3172
            }
3173
            if (periodValid && ch == '.') {
1✔
3174
                periodValid = false;
1✔
3175
                continue;
1✔
3176
            }
3177
            if (ch < '0' || ch > '9') {
1✔
3178
                return false;
1✔
3179
            }
3180
            numberEncountered = true;
1✔
3181
        }
3182
        return numberEncountered;
1✔
3183
    }
3184

3185
    @SuppressWarnings("unchecked")
3186
    public static Map<String, Object> replaceSelfClosingWithNull(Map<String, Object> map) {
3187
        return (Map<String, Object>) replaceSelfClosingWithValue(map, null);
1✔
3188
    }
3189

3190
    @SuppressWarnings("unchecked")
3191
    public static Map<String, Object> replaceSelfClosingWithEmpty(Map<String, Object> map) {
3192
        Object result = replaceSelfClosingWithValue(map, "");
1✔
3193
        if (result instanceof Map) {
1✔
3194
            return (Map<String, Object>) result;
1✔
3195
        }
3196
        return Collections.emptyMap();
1✔
3197
    }
3198

3199
    @SuppressWarnings("unchecked")
3200
    public static Object replaceSelfClosingWithValue(Map<String, Object> map, String value) {
3201
        Object outMap = new LinkedHashMap<>();
1✔
3202
        for (Map.Entry<String, Object> entry : map.entrySet()) {
1✔
3203
            if (SELF_CLOSING.equals(entry.getKey()) && "true".equals(entry.getValue())) {
1✔
3204
                if (map.size() == 1) {
1✔
3205
                    outMap = value;
1✔
3206
                    break;
1✔
3207
                }
3208
            } else {
3209
                ((Map<String, Object>) outMap)
1✔
3210
                        .put(
1✔
3211
                                String.valueOf(entry.getKey()),
1✔
3212
                                makeObjectSelfClose(entry.getValue(), value));
1✔
3213
            }
3214
        }
1✔
3215
        return outMap;
1✔
3216
    }
3217

3218
    @SuppressWarnings("unchecked")
3219
    private static Object makeObjectSelfClose(Object value, String newValue) {
3220
        final Object result;
3221
        if (value instanceof List) {
1✔
3222
            List<Object> values = new ArrayList<>();
1✔
3223
            for (Object item : (List) value) {
1✔
3224
                values.add(
1✔
3225
                        item instanceof Map
1✔
3226
                                ? replaceSelfClosingWithValue((Map) item, newValue)
1✔
3227
                                : item);
1✔
3228
            }
1✔
3229
            result = values;
1✔
3230
        } else if (value instanceof Map) {
1✔
3231
            result = replaceSelfClosingWithValue((Map) value, newValue);
1✔
3232
        } else {
3233
            result = value;
1✔
3234
        }
3235
        return result;
1✔
3236
    }
3237

3238
    public static Map<String, Object> replaceMinusWithAt(Map<String, Object> map) {
3239
        if (map == null) {
1✔
3240
            return null;
1✔
3241
        }
3242
        Map<String, Object> outMap = new LinkedHashMap<>();
1✔
3243
        for (Map.Entry<String, Object> entry : map.entrySet()) {
1✔
3244
            outMap.put(
1✔
3245
                    String.valueOf(entry.getKey()).startsWith("-")
1✔
3246
                            ? "@" + String.valueOf(entry.getKey()).substring(1)
1✔
3247
                            : String.valueOf(entry.getKey()),
1✔
3248
                    replaceMinusWithAtValue(entry.getValue()));
1✔
3249
        }
1✔
3250
        return outMap;
1✔
3251
    }
3252

3253
    @SuppressWarnings("unchecked")
3254
    private static Object replaceMinusWithAtValue(Object value) {
3255
        final Object result;
3256
        if (value instanceof List) {
1✔
3257
            List<Object> values = new ArrayList<>();
1✔
3258
            for (Object item : (List) value) {
1✔
3259
                values.add(item instanceof Map ? replaceMinusWithAt((Map) item) : item);
1✔
3260
            }
1✔
3261
            result = values;
1✔
3262
        } else if (value instanceof Map) {
1✔
3263
            result = replaceMinusWithAt((Map) value);
1✔
3264
        } else {
3265
            result = value;
1✔
3266
        }
3267
        return result;
1✔
3268
    }
3269

3270
    public static Map<String, Object> replaceEmptyValueWithNull(Map<String, Object> map) {
3271
        if (map == null || map.isEmpty()) {
1✔
3272
            return null;
1✔
3273
        }
3274
        Map<String, Object> outMap = new LinkedHashMap<>();
1✔
3275
        for (Map.Entry<String, Object> entry : map.entrySet()) {
1✔
3276
            outMap.put(String.valueOf(entry.getKey()), makeObjectEmptyValue(entry.getValue()));
1✔
3277
        }
1✔
3278
        return outMap;
1✔
3279
    }
3280

3281
    @SuppressWarnings("unchecked")
3282
    private static Object makeObjectEmptyValue(Object value) {
3283
        final Object result;
3284
        if (value instanceof List) {
1✔
3285
            List<Object> values = new ArrayList<>();
1✔
3286
            for (Object item : (List) value) {
1✔
3287
                values.add(item instanceof Map ? replaceEmptyValueWithNull((Map) item) : item);
1✔
3288
            }
1✔
3289
            result = values;
1✔
3290
        } else if (value instanceof Map) {
1✔
3291
            result = replaceEmptyValueWithNull((Map) value);
1✔
3292
        } else {
3293
            result = value;
1✔
3294
        }
3295
        return result;
1✔
3296
    }
3297

3298
    public static Object replaceEmptyValueWithEmptyString(Map<String, Object> map) {
3299
        if (map.isEmpty()) {
1✔
3300
            return "";
1✔
3301
        }
3302
        Map<String, Object> outMap = new LinkedHashMap<>();
1✔
3303
        for (Map.Entry<String, Object> entry : map.entrySet()) {
1✔
3304
            outMap.put(String.valueOf(entry.getKey()), makeObjectEmptyString(entry.getValue()));
1✔
3305
        }
1✔
3306
        return outMap;
1✔
3307
    }
3308

3309
    @SuppressWarnings("unchecked")
3310
    private static Object makeObjectEmptyString(Object value) {
3311
        final Object result;
3312
        if (value instanceof List) {
1✔
3313
            List<Object> values = new ArrayList<>();
1✔
3314
            for (Object item : (List) value) {
1✔
3315
                values.add(
1✔
3316
                        item instanceof Map ? replaceEmptyValueWithEmptyString((Map) item) : item);
1✔
3317
            }
1✔
3318
            result = values;
1✔
3319
        } else if (value instanceof Map) {
1✔
3320
            result = replaceEmptyValueWithEmptyString((Map) value);
1✔
3321
        } else {
3322
            result = value;
1✔
3323
        }
3324
        return result;
1✔
3325
    }
3326

3327
    public static Map<String, Object> forceAttributeUsage(Map<String, Object> map) {
3328
        Map<String, Object> outMap = new LinkedHashMap<>();
1✔
3329
        for (Map.Entry<String, Object> entry : map.entrySet()) {
1✔
3330
            outMap.put(
1✔
3331
                    entry.getValue() instanceof Map
1✔
3332
                                    || entry.getValue() instanceof List
1✔
3333
                                    || String.valueOf(entry.getKey()).startsWith("-")
1✔
3334
                            ? String.valueOf(entry.getKey())
1✔
3335
                            : "-" + entry.getKey(),
1✔
3336
                    makeAttributeUsage(entry.getValue()));
1✔
3337
        }
1✔
3338
        return outMap;
1✔
3339
    }
3340

3341
    @SuppressWarnings("unchecked")
3342
    private static Object makeAttributeUsage(Object value) {
3343
        final Object result;
3344
        if (value instanceof List) {
1✔
3345
            List<Object> values = new ArrayList<>();
1✔
3346
            for (Object item : (List) value) {
1✔
3347
                values.add(item instanceof Map ? forceAttributeUsage((Map) item) : item);
1✔
3348
            }
1✔
3349
            result = values;
1✔
3350
        } else if (value instanceof Map) {
1✔
3351
            result = forceAttributeUsage((Map) value);
1✔
3352
        } else {
3353
            result = value;
1✔
3354
        }
3355
        return result;
1✔
3356
    }
3357

3358
    public static Map<String, Object> replaceNullWithEmptyValue(Map<String, Object> map) {
3359
        Map<String, Object> outMap = new LinkedHashMap<>();
1✔
3360
        for (Map.Entry<String, Object> entry : map.entrySet()) {
1✔
3361
            outMap.put(
1✔
3362
                    entry.getKey(),
1✔
3363
                    entry.getValue() == null
1✔
3364
                            ? new LinkedHashMap<>()
1✔
3365
                            : makeReplaceNullValue(entry.getValue()));
1✔
3366
        }
1✔
3367
        return outMap;
1✔
3368
    }
3369

3370
    @SuppressWarnings("unchecked")
3371
    private static Object makeReplaceNullValue(Object value) {
3372
        final Object result;
3373
        if (value instanceof List) {
1✔
3374
            List<Object> values = new ArrayList<>();
1✔
3375
            for (Object item : (List) value) {
1✔
3376
                values.add(item instanceof Map ? replaceNullWithEmptyValue((Map) item) : item);
1✔
3377
            }
1✔
3378
            result = values;
1✔
3379
        } else if (value instanceof Map) {
1✔
3380
            result = replaceNullWithEmptyValue((Map) value);
1✔
3381
        } else {
3382
            result = value;
1✔
3383
        }
3384
        return result;
1✔
3385
    }
3386

3387
    public static Map<String, Object> replaceEmptyStringWithEmptyValue(Map<String, Object> map) {
3388
        Map<String, Object> outMap = new LinkedHashMap<>();
1✔
3389
        for (Map.Entry<String, Object> entry : map.entrySet()) {
1✔
3390
            outMap.put(
1✔
3391
                    entry.getKey(),
1✔
3392
                    "".equals(entry.getValue())
1✔
3393
                            ? new LinkedHashMap<>()
1✔
3394
                            : makeReplaceEmptyString(entry.getValue()));
1✔
3395
        }
1✔
3396
        return outMap;
1✔
3397
    }
3398

3399
    @SuppressWarnings("unchecked")
3400
    private static Object makeReplaceEmptyString(Object value) {
3401
        final Object result;
3402
        if (value instanceof List) {
1✔
3403
            List<Object> values = new ArrayList<>();
1✔
3404
            for (Object item : (List) value) {
1✔
3405
                values.add(
1✔
3406
                        item instanceof Map ? replaceEmptyStringWithEmptyValue((Map) item) : item);
1✔
3407
            }
1✔
3408
            result = values;
1✔
3409
        } else if (value instanceof Map) {
1✔
3410
            result = replaceEmptyStringWithEmptyValue((Map) value);
1✔
3411
        } else {
3412
            result = value;
1✔
3413
        }
3414
        return result;
1✔
3415
    }
3416

3417
    public static Map<String, Object> replaceNumberAndBooleanWithString(Map<String, Object> map) {
3418
        Map<String, Object> outMap = new LinkedHashMap<>();
1✔
3419
        for (Map.Entry<String, Object> entry : map.entrySet()) {
1✔
3420
            outMap.put(
1✔
3421
                    entry.getKey(),
1✔
3422
                    entry.getValue() instanceof Boolean || entry.getValue() instanceof Number
1✔
3423
                            ? String.valueOf(entry.getValue())
1✔
3424
                            : makeReplaceNumberAndBoolean(entry.getValue()));
1✔
3425
        }
1✔
3426
        return outMap;
1✔
3427
    }
3428

3429
    @SuppressWarnings("unchecked")
3430
    private static Object makeReplaceNumberAndBoolean(Object value) {
3431
        final Object result;
3432
        if (value instanceof List) {
1✔
3433
            List<Object> values = new ArrayList<>();
1✔
3434
            for (Object item : (List) value) {
1✔
3435
                if (item instanceof Map) {
1✔
3436
                    values.add(replaceNumberAndBooleanWithString((Map) item));
1✔
3437
                } else if (item instanceof Number || item instanceof Boolean || isNull(item)) {
1✔
3438
                    values.add(String.valueOf(item));
1✔
3439
                } else {
3440
                    values.add(item);
1✔
3441
                }
3442
            }
1✔
3443
            result = values;
1✔
3444
        } else if (value instanceof Map) {
1✔
3445
            result = replaceNumberAndBooleanWithString((Map) value);
1✔
3446
        } else if (isNull(value)) {
1✔
3447
            result = "null";
1✔
3448
        } else {
3449
            result = value;
1✔
3450
        }
3451
        return result;
1✔
3452
    }
3453

3454
    public static Map<String, Object> replaceFirstLevel(Map<String, Object> map) {
3455
        return replaceFirstLevel(map, 0);
1✔
3456
    }
3457

3458
    @SuppressWarnings("unchecked")
3459
    public static Map<String, Object> replaceFirstLevel(Map<String, Object> map, int level) {
3460
        Map<String, Object> outMap = new LinkedHashMap<>();
1✔
3461
        for (Map.Entry<String, Object> entry : map.entrySet()) {
1✔
3462
            outMap.put(entry.getKey(), makeReplaceFirstLevel(entry.getValue(), level + 1));
1✔
3463
        }
1✔
3464
        if (level == 0 && Xml.XmlValue.getMapValue(outMap) instanceof Map) {
1✔
3465
            Map<String, Object> outMap2 = (Map<String, Object>) Xml.XmlValue.getMapValue(outMap);
1✔
3466
            if (SELF_CLOSING.equals(Xml.XmlValue.getMapKey(outMap2))
1✔
3467
                    && "true".equals(Xml.XmlValue.getMapValue(outMap2))) {
1✔
3468
                outMap2.remove(SELF_CLOSING);
1✔
3469
            }
3470
            return outMap2;
1✔
3471
        }
3472
        return outMap;
1✔
3473
    }
3474

3475
    @SuppressWarnings("unchecked")
3476
    private static Object makeReplaceFirstLevel(Object value, int level) {
3477
        final Object result;
3478
        if (value instanceof List) {
1✔
3479
            List<Object> values = new ArrayList<>();
1✔
3480
            for (Object item : (List) value) {
1✔
3481
                values.add(item instanceof Map ? replaceFirstLevel((Map) item, level + 1) : item);
1✔
3482
            }
1✔
3483
            result = values;
1✔
3484
        } else if (value instanceof Map) {
1✔
3485
            result = replaceFirstLevel((Map) value, level + 1);
1✔
3486
        } else {
3487
            result = value;
1✔
3488
        }
3489
        return result;
1✔
3490
    }
3491

3492
    public static Map<String, Object> replaceNilWithNull(Map<String, Object> map) {
3493
        Map<String, Object> outMap = new LinkedHashMap<>();
1✔
3494
        for (Map.Entry<String, Object> entry : map.entrySet()) {
1✔
3495
            Object outValue = makeReplaceNilWithNull(entry.getValue());
1✔
3496
            if (outValue instanceof Map
1✔
3497
                    && (NIL_KEY.equals(Xml.XmlValue.getMapKey(outValue))
1✔
3498
                            || Xml.XmlValue.getMapKey(outValue).endsWith(":nil"))
1✔
3499
                    && "true".equals(Xml.XmlValue.getMapValue(outValue))
1✔
3500
                    && ((Map) outValue).containsKey(SELF_CLOSING)
1✔
3501
                    && "true".equals(((Map) outValue).get(SELF_CLOSING))) {
1✔
3502
                outValue = null;
1✔
3503
            }
3504
            outMap.put(entry.getKey(), outValue);
1✔
3505
        }
1✔
3506
        return outMap;
1✔
3507
    }
3508

3509
    @SuppressWarnings("unchecked")
3510
    private static Object makeReplaceNilWithNull(Object value) {
3511
        final Object result;
3512
        if (value instanceof List) {
1✔
3513
            List<Object> values = new ArrayList<>();
1✔
3514
            for (Object item : (List) value) {
1✔
3515
                values.add(item instanceof Map ? replaceNilWithNull((Map) item) : item);
1✔
3516
            }
1✔
3517
            result = values;
1✔
3518
        } else if (value instanceof Map) {
1✔
3519
            result = replaceNilWithNull((Map) value);
1✔
3520
        } else {
3521
            result = value;
1✔
3522
        }
3523
        return result;
1✔
3524
    }
3525

3526
    public static Map<String, Object> deepCopyMap(Map<String, Object> map) {
3527
        Map<String, Object> outMap = new LinkedHashMap<>();
1✔
3528
        for (Map.Entry<String, Object> entry : map.entrySet()) {
1✔
3529
            outMap.put(entry.getKey(), makeDeepCopyMap(entry.getValue()));
1✔
3530
        }
1✔
3531
        return outMap;
1✔
3532
    }
3533

3534
    @SuppressWarnings("unchecked")
3535
    private static Object makeDeepCopyMap(Object value) {
3536
        final Object result;
3537
        if (value instanceof List) {
1✔
3538
            List<Object> values = new ArrayList<>();
1✔
3539
            for (Object item : (List) value) {
1✔
3540
                values.add(item instanceof Map ? deepCopyMap((Map) item) : item);
1✔
3541
            }
1✔
3542
            result = values;
1✔
3543
        } else if (value instanceof Map) {
1✔
3544
            result = deepCopyMap((Map) value);
1✔
3545
        } else {
3546
            result = value;
1✔
3547
        }
3548
        return result;
1✔
3549
    }
3550

3551
    public static Builder objectBuilder() {
3552
        return new U.Builder();
1✔
3553
    }
3554

3555
    public static class Builder {
3556
        private final Map<String, Object> data;
3557

3558
        public Builder() {
1✔
3559
            data = new LinkedHashMap<>();
1✔
3560
        }
1✔
3561

3562
        public Builder add(final String key, final Object value) {
3563
            data.put(key, value);
1✔
3564
            return this;
1✔
3565
        }
3566

3567
        public Builder add(final Object value) {
3568
            data.put(String.valueOf(data.size()), value);
1✔
3569
            return this;
1✔
3570
        }
3571

3572
        public <T> T get(final String path) {
3573
            return U.get(data, path);
1✔
3574
        }
3575

3576
        public <T> T get(final List<String> paths) {
3577
            return U.get(data, paths);
1✔
3578
        }
3579

3580
        public Builder set(final String path, final Object value) {
3581
            U.set(data, path, value);
1✔
3582
            return this;
1✔
3583
        }
3584

3585
        public Builder set(final List<String> paths, final Object value) {
3586
            U.set(data, paths, value);
1✔
3587
            return this;
1✔
3588
        }
3589

3590
        public Builder remove(final String key) {
3591
            U.remove(data, key);
1✔
3592
            return this;
1✔
3593
        }
3594

3595
        public Builder remove(final List<String> keys) {
3596
            U.remove(data, keys);
1✔
3597
            return this;
1✔
3598
        }
3599

3600
        public Builder clear() {
3601
            data.clear();
1✔
3602
            return this;
1✔
3603
        }
3604

3605
        public boolean isEmpty() {
3606
            return data.isEmpty();
1✔
3607
        }
3608

3609
        public int size() {
3610
            return data.size();
1✔
3611
        }
3612

3613
        public Builder add(final Builder builder) {
3614
            data.put(String.valueOf(data.size()), builder.build());
1✔
3615
            return this;
1✔
3616
        }
3617

3618
        public Builder add(final String key, final ArrayBuilder builder) {
3619
            data.put(key, builder.build());
1✔
3620
            return this;
1✔
3621
        }
3622

3623
        public Builder add(final String key, final Builder builder) {
3624
            data.put(key, builder.build());
1✔
3625
            return this;
1✔
3626
        }
3627

3628
        public Builder add(final Map<String, Object> map) {
3629
            data.putAll(deepCopyMap(map));
1✔
3630
            return this;
1✔
3631
        }
3632

3633
        public Builder update(final Map<String, Object> map) {
3634
            U.update(data, deepCopyMap(map));
1✔
3635
            return this;
1✔
3636
        }
3637

3638
        public Builder addNull(final String key) {
3639
            data.put(key, null);
1✔
3640
            return this;
1✔
3641
        }
3642

3643
        @SuppressWarnings("unchecked")
3644
        public Map<String, Object> build() {
3645
            return (Map<String, Object>) ((LinkedHashMap<?, ?>) data).clone();
1✔
3646
        }
3647

3648
        public String toXml() {
3649
            return Xml.toXml(data);
1✔
3650
        }
3651

3652
        public static Builder fromXml(final String xml) {
3653
            final Builder builder = new Builder();
1✔
3654
            builder.data.putAll(fromXmlMap(xml));
1✔
3655
            return builder;
1✔
3656
        }
3657

3658
        public static Builder fromMap(final Map<String, Object> map) {
3659
            final Builder builder = new Builder();
1✔
3660
            builder.data.putAll(deepCopyMap(map));
1✔
3661
            return builder;
1✔
3662
        }
3663

3664
        public String toJson() {
3665
            return Json.toJson(data);
1✔
3666
        }
3667

3668
        public static Builder fromJson(final String json) {
3669
            final Builder builder = new Builder();
1✔
3670
            builder.data.putAll(fromJsonMap(json));
1✔
3671
            return builder;
1✔
3672
        }
3673

3674
        public Chain<Object> toChain() {
3675
            return new U.Chain<>(data.entrySet());
1✔
3676
        }
3677

3678
        @Override
3679
        public String toString() {
3680
            return data.toString();
1✔
3681
        }
3682
    }
3683

3684
    public static ArrayBuilder arrayBuilder() {
3685
        return new U.ArrayBuilder();
1✔
3686
    }
3687

3688
    public static class ArrayBuilder {
3689
        private final List<Object> data;
3690

3691
        public ArrayBuilder() {
1✔
3692
            data = new ArrayList<>();
1✔
3693
        }
1✔
3694

3695
        public ArrayBuilder add(final Object value) {
3696
            data.add(value);
1✔
3697
            return this;
1✔
3698
        }
3699

3700
        public ArrayBuilder addNull() {
3701
            data.add(null);
1✔
3702
            return this;
1✔
3703
        }
3704

3705
        public <T> T get(final String path) {
3706
            return U.get(U.getStringObjectMap(data), "value." + path);
1✔
3707
        }
3708

3709
        public <T> T get(final List<String> paths) {
3710
            List<String> newPaths = new ArrayList<>();
1✔
3711
            newPaths.add("value");
1✔
3712
            newPaths.addAll(paths);
1✔
3713
            return U.get(U.getStringObjectMap(data), newPaths);
1✔
3714
        }
3715

3716
        public ArrayBuilder set(final int index, final Object value) {
3717
            data.set(index, value);
1✔
3718
            return this;
1✔
3719
        }
3720

3721
        public ArrayBuilder remove(final int index) {
3722
            data.remove(index);
1✔
3723
            return this;
1✔
3724
        }
3725

3726
        public ArrayBuilder clear() {
3727
            data.clear();
1✔
3728
            return this;
1✔
3729
        }
3730

3731
        public boolean isEmpty() {
3732
            return data.isEmpty();
1✔
3733
        }
3734

3735
        public int size() {
3736
            return data.size();
1✔
3737
        }
3738

3739
        public ArrayBuilder add(final ArrayBuilder builder) {
3740
            data.addAll(builder.build());
1✔
3741
            return this;
1✔
3742
        }
3743

3744
        public ArrayBuilder add(final Builder builder) {
3745
            data.add(builder.build());
1✔
3746
            return this;
1✔
3747
        }
3748

3749
        @SuppressWarnings("unchecked")
3750
        public ArrayBuilder merge(final List<Object> list) {
3751
            U.merge(data, (List<Object>) ((ArrayList<?>) list).clone());
1✔
3752
            return this;
1✔
3753
        }
3754

3755
        @SuppressWarnings("unchecked")
3756
        public List<Object> build() {
3757
            return (List<Object>) ((ArrayList<?>) data).clone();
1✔
3758
        }
3759

3760
        public String toXml() {
3761
            return Xml.toXml(data);
1✔
3762
        }
3763

3764
        public static ArrayBuilder fromXml(final String xml) {
3765
            final ArrayBuilder builder = new ArrayBuilder();
1✔
3766
            builder.data.addAll(U.<List<Object>>fromXml(xml));
1✔
3767
            return builder;
1✔
3768
        }
3769

3770
        public String toJson() {
3771
            return Json.toJson(data);
1✔
3772
        }
3773

3774
        public static ArrayBuilder fromJson(final String json) {
3775
            final ArrayBuilder builder = new ArrayBuilder();
1✔
3776
            builder.data.addAll(U.<List<Object>>fromJson(json));
1✔
3777
            return builder;
1✔
3778
        }
3779

3780
        public Chain<Object> toChain() {
3781
            return new U.Chain<>(data);
1✔
3782
        }
3783

3784
        @Override
3785
        public String toString() {
3786
            return data.toString();
1✔
3787
        }
3788
    }
3789

3790
    public static Map<String, Object> propertiesToMap(Properties properties) {
3791
        Map<String, Object> map = new LinkedHashMap<>();
1✔
3792
        if (properties != null && !properties.isEmpty()) {
1✔
3793
            Enumeration<?> enumProperties = properties.propertyNames();
1✔
3794
            while (enumProperties.hasMoreElements()) {
1✔
3795
                String name = (String) enumProperties.nextElement();
1✔
3796
                map.put(name, properties.getProperty(name));
1✔
3797
            }
1✔
3798
        }
3799
        return map;
1✔
3800
    }
3801

3802
    public static Properties mapToProperties(Map<String, Object> map) {
3803
        Properties properties = new Properties();
1✔
3804
        if (map != null) {
1✔
3805
            for (final Map.Entry<String, Object> entry : map.entrySet()) {
1✔
3806
                if (!isNull(entry.getValue())) {
1✔
3807
                    properties.put(entry.getKey(), String.valueOf(entry.getValue()));
1✔
3808
                }
3809
            }
1✔
3810
        }
3811
        return properties;
1✔
3812
    }
3813
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc