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

javadev / underscore-java / #3785

04 Apr 2024 04:41AM UTC coverage: 100.0%. Remained the same
#3785

push

web-flow
Merge fa30c8ad9 into f441cc437

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

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

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

136
    public enum XmlToJsonMode {
1✔
137
        REPLACE_SELF_CLOSING_WITH_NULL,
1✔
138
        REPLACE_SELF_CLOSING_WITH_STRING,
1✔
139
        REPLACE_EMPTY_VALUE_WITH_NULL,
1✔
140
        REPLACE_EMPTY_TAG_WITH_NULL,
1✔
141
        REPLACE_EMPTY_TAG_WITH_STRING,
1✔
142
        REMOVE_FIRST_LEVEL,
1✔
143
        WITHOUT_NAMESPACES,
1✔
144
        REPLACE_MINUS_WITH_AT,
1✔
145
        REPLACE_EMPTY_TAG_WITH_NULL_AND_MINUS_WITH_AT
1✔
146
    }
147

148
    public enum JsonToXmlMode {
1✔
149
        FORCE_ATTRIBUTE_USAGE,
1✔
150
        DEFINE_ROOT_NAME,
1✔
151
        REPLACE_NULL_WITH_EMPTY_VALUE,
1✔
152
        REPLACE_EMPTY_STRING_WITH_EMPTY_VALUE,
1✔
153
        ADD_ROOT,
1✔
154
        REMOVE_ARRAY_ATTRIBUTE,
1✔
155
        REMOVE_ATTRIBUTES
1✔
156
    }
157

158
    public U(final Iterable<T> iterable) {
159
        super(iterable);
1✔
160
    }
1✔
161

162
    public U(final String string) {
163
        super(string);
1✔
164
    }
1✔
165

166
    public static class Chain<T> extends Underscore.Chain<T> {
167
        public Chain(final T item) {
168
            super(item);
1✔
169
        }
1✔
170

171
        public Chain(final List<T> list) {
172
            super(list);
1✔
173
        }
1✔
174

175
        public Chain(final Map<String, Object> map) {
176
            super(map);
1✔
177
        }
1✔
178

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

184
        @Override
185
        public Chain<T> first(int n) {
186
            return new Chain<>(Underscore.first(value(), n));
1✔
187
        }
188

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

194
        @Override
195
        public Chain<T> firstOrNull(final Predicate<T> pred) {
196
            return new Chain<>(Underscore.firstOrNull(value(), pred));
1✔
197
        }
198

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

204
        @Override
205
        public Chain<T> initial(int n) {
206
            return new Chain<>(Underscore.initial(value(), n));
1✔
207
        }
208

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

214
        @Override
215
        public Chain<T> last(int n) {
216
            return new Chain<>(Underscore.last(value(), n));
1✔
217
        }
218

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

224
        @Override
225
        public Chain<T> lastOrNull(final Predicate<T> pred) {
226
            return new Chain<>(Underscore.lastOrNull(value(), pred));
1✔
227
        }
228

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

234
        @Override
235
        public Chain<T> rest(int n) {
236
            return new Chain<>(Underscore.rest(value(), n));
1✔
237
        }
238

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

244
        @Override
245
        public Chain<T> compact(final T falsyValue) {
246
            return new Chain<>(Underscore.compact(value(), falsyValue));
1✔
247
        }
248

249
        @Override
250
        public Chain flatten() {
251
            return new Chain<>(Underscore.flatten(value()));
1✔
252
        }
253

254
        @Override
255
        public <F> Chain<F> map(final Function<? super T, F> func) {
256
            return new Chain<>(Underscore.map(value(), func));
1✔
257
        }
258

259
        @Override
260
        public <F> Chain<F> mapMulti(final BiConsumer<? super T, ? super Consumer<F>> mapper) {
261
            return new Chain<>(Underscore.mapMulti(value(), mapper));
1✔
262
        }
263

264
        @Override
265
        public <F> Chain<F> mapIndexed(final BiFunction<Integer, ? super T, F> func) {
266
            return new Chain<>(Underscore.mapIndexed(value(), func));
1✔
267
        }
268

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

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

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

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

289
        @Override
290
        public Chain<T> filterFalse(final Predicate<T> pred) {
291
            return new Chain<>(Underscore.filterFalse(value(), pred));
1✔
292
        }
293

294
        @Override
295
        public <F> Chain<F> reduce(final BiFunction<F, T, F> func, final F zeroElem) {
296
            return new Chain<>(Underscore.reduce(value(), func, zeroElem));
1✔
297
        }
298

299
        @Override
300
        public Chain<Optional<T>> reduce(final BinaryOperator<T> func) {
301
            return new Chain<>(Underscore.reduce(value(), func));
1✔
302
        }
303

304
        @Override
305
        public <F> Chain<F> reduceRight(final BiFunction<F, T, F> func, final F zeroElem) {
306
            return new Chain<>(Underscore.reduceRight(value(), func, zeroElem));
1✔
307
        }
308

309
        @Override
310
        public Chain<Optional<T>> reduceRight(final BinaryOperator<T> func) {
311
            return new Chain<>(Underscore.reduceRight(value(), func));
1✔
312
        }
313

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

319
        @Override
320
        public Chain<Optional<T>> findLast(final Predicate<T> pred) {
321
            return new Chain<>(Underscore.findLast(value(), pred));
1✔
322
        }
323

324
        @Override
325
        @SuppressWarnings("unchecked")
326
        public Chain<Comparable> max() {
327
            return new Chain<>(Underscore.max((Collection) value()));
1✔
328
        }
329

330
        @Override
331
        public <F extends Comparable<? super F>> Chain<T> max(final Function<T, F> func) {
332
            return new Chain<>(Underscore.max(value(), func));
1✔
333
        }
334

335
        @Override
336
        @SuppressWarnings("unchecked")
337
        public Chain<Comparable> min() {
338
            return new Chain<>(Underscore.min((Collection) value()));
1✔
339
        }
340

341
        @Override
342
        public <F extends Comparable<? super F>> Chain<T> min(final Function<T, F> func) {
343
            return new Chain<>(Underscore.min(value(), func));
1✔
344
        }
345

346
        @Override
347
        @SuppressWarnings("unchecked")
348
        public Chain<Comparable> sort() {
349
            return new Chain<>(Underscore.sort((List<Comparable>) value()));
1✔
350
        }
351

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

358
        @Override
359
        public <F extends Comparable<? super F>> Chain<T> sortBy(final Function<T, F> func) {
360
            return new Chain<>(Underscore.sortBy(value(), func));
1✔
361
        }
362

363
        @Override
364
        @SuppressWarnings("unchecked")
365
        public <K> Chain<Map<K, Comparable>> sortBy(final K key) {
366
            return new Chain<>(Underscore.sortBy((List<Map<K, Comparable>>) value(), key));
1✔
367
        }
368

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

374
        @Override
375
        public <F> Chain<Map<F, T>> associateBy(final Function<T, F> func) {
376
            return new Chain<>(Underscore.associateBy(value(), func));
1✔
377
        }
378

379
        @Override
380
        public <F> Chain<Map<F, Optional<T>>> groupBy(
381
                final Function<T, F> func, final BinaryOperator<T> binaryOperator) {
382
            return new Chain<>(Underscore.groupBy(value(), func, binaryOperator));
1✔
383
        }
384

385
        @Override
386
        public Chain<Map<Object, List<T>>> indexBy(final String property) {
387
            return new Chain<>(Underscore.indexBy(value(), property));
1✔
388
        }
389

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

395
        @Override
396
        public Chain<Map<T, Integer>> countBy() {
397
            return new Chain<>(Underscore.countBy(value()));
1✔
398
        }
399

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

405
        @Override
406
        public Chain<T> sample() {
407
            return new Chain<>(Underscore.sample(value()));
1✔
408
        }
409

410
        @Override
411
        public Chain<T> sample(final int howMany) {
412
            return new Chain<>(newArrayList(Underscore.sample(value(), howMany)));
1✔
413
        }
414

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

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

427
        @Override
428
        public Chain<T> forEachRight(final Consumer<T> func) {
429
            Underscore.forEachRight(value(), func);
1✔
430
            return new Chain<>(value());
1✔
431
        }
432

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

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

443
        @Override
444
        public Chain<Integer> count(final Predicate<T> pred) {
445
            return new Chain<>(Underscore.count(value(), pred));
1✔
446
        }
447

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

453
        @Override
454
        public Chain<Boolean> containsWith(final T elem) {
455
            return new Chain<>(Underscore.containsWith(value(), elem));
1✔
456
        }
457

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

463
        @Override
464
        public Chain<T> invoke(final String methodName) {
465
            return new Chain<>(Underscore.invoke(value(), methodName));
1✔
466
        }
467

468
        @Override
469
        public Chain<Object> pluck(final String propertyName) {
470
            return new Chain<>(Underscore.pluck(value(), propertyName));
1✔
471
        }
472

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

478
        @Override
479
        public <E> Chain<Optional<T>> findWhere(final List<Map.Entry<String, E>> properties) {
480
            return new Chain<>(Underscore.findWhere(value(), properties));
1✔
481
        }
482

483
        @Override
484
        public Chain<T> uniq() {
485
            return new Chain<>(Underscore.uniq(value()));
1✔
486
        }
487

488
        @Override
489
        public <F> Chain<T> uniq(final Function<T, F> func) {
490
            return new Chain<>(newArrayList(Underscore.uniq(value(), func)));
1✔
491
        }
492

493
        @Override
494
        public Chain<T> distinct() {
495
            return new Chain<>(Underscore.uniq(value()));
1✔
496
        }
497

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

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

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

516
        @Override
517
        @SuppressWarnings("unchecked")
518
        public Chain<T> difference(final List<T>... lists) {
519
            return new Chain<>(Underscore.difference(value(), lists));
1✔
520
        }
521

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

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

532
        @Override
533
        public Chain<Integer> range(final int start, final int stop, final int step) {
534
            return new Chain<>(Underscore.range(start, stop, step));
1✔
535
        }
536

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

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

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

552
        @Override
553
        public Chain<List<T>> chunkFill(final int size, final int step, final T fillValue) {
554
            return new Chain<>(Underscore.chunkFill(value(), size, step, fillValue));
1✔
555
        }
556

557
        @Override
558
        public Chain<T> cycle(final int times) {
559
            return new Chain<>(Underscore.cycle(value(), times));
1✔
560
        }
561

562
        @Override
563
        public Chain<T> interpose(final T element) {
564
            return new Chain<>(Underscore.interpose(value(), element));
1✔
565
        }
566

567
        @Override
568
        public Chain<T> interposeByList(final Iterable<T> interIter) {
569
            return new Chain<>(Underscore.interposeByList(value(), interIter));
1✔
570
        }
571

572
        @Override
573
        @SuppressWarnings("unchecked")
574
        public Chain<T> concat(final List<T>... lists) {
575
            return new Chain<>(Underscore.concat(value(), lists));
1✔
576
        }
577

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

583
        @Override
584
        public Chain<T> slice(final int start, final int end) {
585
            return new Chain<>(Underscore.slice(value(), start, end));
1✔
586
        }
587

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

593
        public Chain<Map<String, Object>> set(final List<String> paths, Object value) {
594
            U.set(map(), paths, value);
1✔
595
            return new Chain<>(map());
1✔
596
        }
597

598
        @Override
599
        public Chain<T> reverse() {
600
            return new Chain<>(Underscore.reverse(value()));
1✔
601
        }
602

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

608
        @Override
609
        public Chain<String> join(final String separator) {
610
            return new Chain<>(Underscore.join(value(), separator));
1✔
611
        }
612

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

618
        @Override
619
        public Chain<T> limit(final int size) {
620
            return new Chain<>(value().subList(0, size));
1✔
621
        }
622

623
        @Override
624
        @SuppressWarnings("unchecked")
625
        public <K, V> Chain<Map<K, V>> toMap() {
626
            return new Chain<>(Underscore.toMap((Iterable<Map.Entry<K, V>>) value()));
1✔
627
        }
628

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

633
        public Chain<T> drop(final Integer n) {
634
            return new Chain<>(Underscore.drop(value(), n));
1✔
635
        }
636

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

641
        public Chain<T> dropRight(final Integer n) {
642
            return new Chain<>(U.dropRight(value(), n));
1✔
643
        }
644

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

649
        public Chain<T> dropRightWhile(final Predicate<T> pred) {
650
            return new Chain<>(U.dropRightWhile(value(), pred));
1✔
651
        }
652

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

658
        @SuppressWarnings("unchecked")
659
        public Chain<Object> fill(final Object value, final Integer start, final Integer end) {
660
            return new Chain<>(U.fill((List<Object>) value(), value, start, end));
1✔
661
        }
662

663
        public Chain<Object> flattenDeep() {
664
            return new Chain<>(U.flattenDeep(value()));
1✔
665
        }
666

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

672
        @SuppressWarnings("unchecked")
673
        public Chain<Object> pullAt(final Integer... indexes) {
674
            return new Chain<>(U.pullAt((List<Object>) value(), indexes));
1✔
675
        }
676

677
        public Chain<T> remove(final Predicate<T> pred) {
678
            return new Chain<>(U.remove(value(), pred));
1✔
679
        }
680

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

685
        public Chain<T> takeRight() {
686
            return new Chain<>(U.takeRight(value()));
1✔
687
        }
688

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

693
        public Chain<T> takeRight(final Integer n) {
694
            return new Chain<>(U.takeRight(value(), n));
1✔
695
        }
696

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

701
        public Chain<T> takeRightWhile(final Predicate<T> pred) {
702
            return new Chain<>(U.takeRightWhile(value(), pred));
1✔
703
        }
704

705
        @SuppressWarnings("unchecked")
706
        public Chain<T> xor(final List<T> list) {
707
            return new Chain<>(U.xor(value(), list));
1✔
708
        }
709

710
        public Chain<T> at(final Integer... indexes) {
711
            return new Chain<>(U.at(value(), indexes));
1✔
712
        }
713

714
        @SuppressWarnings("unchecked")
715
        public <F extends Number> Chain<F> sum() {
716
            return new Chain<>(U.sum((List<F>) value()));
1✔
717
        }
718

719
        public <F extends Number> Chain<F> sum(final Function<T, F> func) {
720
            return new Chain<>(U.sum(value(), func));
1✔
721
        }
722

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

728
        @SuppressWarnings("unchecked")
729
        public Chain<Double> median() {
730
            return new Chain<>(U.median((List<Number>) value()));
1✔
731
        }
732

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

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

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

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

749
        public Chain<String> deburr() {
750
            return new Chain<>(U.deburr((String) item()));
1✔
751
        }
752

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

757
        public Chain<Boolean> endsWith(final String target, final Integer position) {
758
            return new Chain<>(U.endsWith((String) item(), target, position));
1✔
759
        }
760

761
        public Chain<String> kebabCase() {
762
            return new Chain<>(U.kebabCase((String) item()));
1✔
763
        }
764

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

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

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

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

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

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

789
        public Chain<String> padEnd(final int length, final String chars) {
790
            return new Chain<>(U.padEnd((String) item(), length, chars));
1✔
791
        }
792

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

797
        public Chain<String> startCase() {
798
            return new Chain<>(U.startCase((String) item()));
1✔
799
        }
800

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

805
        public Chain<Boolean> startsWith(final String target, final Integer position) {
806
            return new Chain<>(U.startsWith((String) item(), target, position));
1✔
807
        }
808

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

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

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

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

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

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

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

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

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

845
        public Chain<String> words() {
846
            return new Chain<>(U.words((String) item()));
1✔
847
        }
848

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

853
        public Chain<Object> fromJson() {
854
            return new Chain<>(Json.fromJson((String) item()));
1✔
855
        }
856

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

861
        public Chain<Object> fromXml() {
862
            return new Chain<>(Xml.fromXml((String) item()));
1✔
863
        }
864

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

869
        public Chain<String> fetch(final String method, final String body) {
870
            return new Chain<>(U.fetch((String) item(), method, body).text());
1✔
871
        }
872

873
        public Chain<List<T>> createPermutationWithRepetition(final int permutationLength) {
874
            return new Chain<>(U.createPermutationWithRepetition(value(), permutationLength));
1✔
875
        }
876

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

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

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

890
    public static <T> Chain<T> chain(final List<T> list) {
891
        return new U.Chain<>(list);
1✔
892
    }
893

894
    public static Chain<Map<String, Object>> chain(final Map<String, Object> map) {
895
        return new U.Chain<>(map);
1✔
896
    }
897

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

902
    public static <T> Chain<T> chain(final Iterable<T> iterable, int size) {
903
        return new U.Chain<>(newArrayList(iterable, size));
1✔
904
    }
905

906
    @SuppressWarnings("unchecked")
907
    public static <T> Chain<T> chain(final T... list) {
908
        return new U.Chain<>(Arrays.asList(list));
1✔
909
    }
910

911
    public static Chain<Integer> chain(final int[] array) {
912
        return new U.Chain<>(newIntegerList(array));
1✔
913
    }
914

915
    @Override
916
    public Chain<T> chain() {
917
        return new U.Chain<>(newArrayList(value()));
1✔
918
    }
919

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

924
    public static <T> Chain<T> of(final List<T> list) {
925
        return new U.Chain<>(list);
1✔
926
    }
927

928
    public static Chain<Map<String, Object>> of(final Map<String, Object> map) {
929
        return new U.Chain<>(map);
1✔
930
    }
931

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

936
    public static <T> Chain<T> of(final Iterable<T> iterable, int size) {
937
        return new U.Chain<>(newArrayList(iterable, size));
1✔
938
    }
939

940
    @SuppressWarnings("unchecked")
941
    public static <T> Chain<T> of(final T... list) {
942
        return new U.Chain<>(Arrays.asList(list));
1✔
943
    }
944

945
    public static Chain<Integer> of(final int[] array) {
946
        return new U.Chain<>(newIntegerList(array));
1✔
947
    }
948

949
    @Override
950
    public Chain<T> of() {
951
        return new U.Chain<>(newArrayList(value()));
1✔
952
    }
953

954
    public static <T> List<T> drop(final Iterable<T> iterable) {
955
        return rest(newArrayList(iterable));
1✔
956
    }
957

958
    public List<T> drop() {
959
        return drop(getIterable());
1✔
960
    }
961

962
    public static <T> List<T> drop(final Iterable<T> iterable, final Integer n) {
963
        return rest(newArrayList(iterable), n);
1✔
964
    }
965

966
    public List<T> drop(final Integer n) {
967
        return drop(getIterable(), n);
1✔
968
    }
969

970
    public static <T> List<T> dropRight(final Iterable<T> iterable) {
971
        return initial(newArrayList(iterable));
1✔
972
    }
973

974
    public List<T> dropRight() {
975
        return dropRight(getIterable());
1✔
976
    }
977

978
    public static <T> List<T> dropRight(final Iterable<T> iterable, final Integer n) {
979
        return initial(newArrayList(iterable), n);
1✔
980
    }
981

982
    public List<T> dropRight(final Integer n) {
983
        return dropRight(getIterable(), n);
1✔
984
    }
985

986
    public static <T> List<T> dropWhile(final Iterable<T> iterable, final Predicate<T> pred) {
987
        return rest(newArrayList(iterable), findIndex(newArrayList(iterable), negate(pred)));
1✔
988
    }
989

990
    public List<T> dropWhile(final Predicate<T> pred) {
991
        return dropWhile(getIterable(), pred);
1✔
992
    }
993

994
    public static <T> List<T> dropRightWhile(final Iterable<T> iterable, final Predicate<T> pred) {
995
        return reverse(dropWhile(reverse(iterable), pred));
1✔
996
    }
997

998
    public List<T> dropRightWhile(final Predicate<T> pred) {
999
        return dropRightWhile(getIterable(), pred);
1✔
1000
    }
1001

1002
    public static <T> List<T> fill(List<T> list, T item) {
1003
        for (int i = 0; i < size(list); i++) {
1✔
1004
            list.set(i, item);
1✔
1005
        }
1006
        return list;
1✔
1007
    }
1008

1009
    public static <T> T[] fill(T[] array, T item) {
1010
        Arrays.fill(array, item);
1✔
1011
        return array;
1✔
1012
    }
1013

1014
    @SuppressWarnings("unchecked")
1015
    public List<Object> fill(Object value) {
1016
        return fill((List<Object>) getIterable(), value);
1✔
1017
    }
1018

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

1027
    @SuppressWarnings("unchecked")
1028
    public List<Object> fill(Object value, Integer start, Integer end) {
1029
        return fill((List<Object>) getIterable(), value, start, end);
1✔
1030
    }
1031

1032
    public static <E> List<E> flattenDeep(final List<?> list) {
1033
        return flatten(list, false);
1✔
1034
    }
1035

1036
    public List<T> flattenDeep() {
1037
        return flattenDeep((List<?>) getIterable());
1✔
1038
    }
1039

1040
    public static List<Object> pull(final List<Object> list, Object... values) {
1041
        final List<Object> valuesList = Arrays.asList(values);
1✔
1042
        list.removeIf(valuesList::contains);
1✔
1043
        return list;
1✔
1044
    }
1045

1046
    @SuppressWarnings("unchecked")
1047
    public List<Object> pull(Object... values) {
1048
        return pull((List<Object>) getIterable(), values);
1✔
1049
    }
1050

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

1066
    @SuppressWarnings("unchecked")
1067
    public List<Object> pullAt(final Integer... indexes) {
1068
        return pullAt((List<Object>) getIterable(), indexes);
1✔
1069
    }
1070

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

1083
    public List<T> remove(final Predicate<T> pred) {
1084
        return remove((List<T>) getIterable(), pred);
1✔
1085
    }
1086

1087
    public static <T> List<T> take(final Iterable<T> iterable) {
1088
        return first(newArrayList(iterable), 1);
1✔
1089
    }
1090

1091
    public List<T> take() {
1092
        return take(getIterable());
1✔
1093
    }
1094

1095
    public static <T> List<T> takeRight(final Iterable<T> iterable) {
1096
        return last(newArrayList(iterable), 1);
1✔
1097
    }
1098

1099
    public List<T> takeRight() {
1100
        return takeRight(getIterable());
1✔
1101
    }
1102

1103
    public static <T> List<T> take(final Iterable<T> iterable, final Integer n) {
1104
        return first(newArrayList(iterable), n);
1✔
1105
    }
1106

1107
    public List<T> take(final Integer n) {
1108
        return take(getIterable(), n);
1✔
1109
    }
1110

1111
    public static <T> List<T> takeRight(final Iterable<T> iterable, final Integer n) {
1112
        return last(newArrayList(iterable), n);
1✔
1113
    }
1114

1115
    public List<T> takeRight(final Integer n) {
1116
        return takeRight(getIterable(), n);
1✔
1117
    }
1118

1119
    public static <T> List<T> takeWhile(final Iterable<T> iterable, final Predicate<T> pred) {
1120
        return first(newArrayList(iterable), findIndex(newArrayList(iterable), negate(pred)));
1✔
1121
    }
1122

1123
    public List<T> takeWhile(final Predicate<T> pred) {
1124
        return takeWhile(getIterable(), pred);
1✔
1125
    }
1126

1127
    public static <T> List<T> takeRightWhile(final Iterable<T> iterable, final Predicate<T> pred) {
1128
        return reverse(takeWhile(reverse(iterable), pred));
1✔
1129
    }
1130

1131
    public List<T> takeRightWhile(final Predicate<T> pred) {
1132
        return takeRightWhile(getIterable(), pred);
1✔
1133
    }
1134

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

1150
    @SuppressWarnings("unchecked")
1151
    public List<T> xor(final List<T> list) {
1152
        return xor((List<T>) getIterable(), list);
1✔
1153
    }
1154

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

1168
    public List<T> at(final Integer... indexes) {
1169
        return at((List<T>) getIterable(), indexes);
1✔
1170
    }
1171

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

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

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

1197
    public static Double average(java.math.BigDecimal first, java.math.BigDecimal second) {
1198
        if (first == null || second == null) {
1✔
1199
            return null;
1✔
1200
        }
1201
        return sum(first, second).doubleValue() / 2;
1✔
1202
    }
1203

1204
    public static Double average(java.math.BigInteger first, java.math.BigInteger second) {
1205
        if (first == null || second == null) {
1✔
1206
            return null;
1✔
1207
        }
1208
        return sum(first, second).doubleValue() / 2;
1✔
1209
    }
1210

1211
    public static Double average(Byte first, Byte second) {
1212
        if (first == null || second == null) {
1✔
1213
            return null;
1✔
1214
        }
1215
        return sum(first, second).doubleValue() / 2;
1✔
1216
    }
1217

1218
    public static Double average(Double first, Double second) {
1219
        if (first == null || second == null) {
1✔
1220
            return null;
1✔
1221
        }
1222
        return sum(first, second) / 2;
1✔
1223
    }
1224

1225
    public static Double average(Float first, Float second) {
1226
        if (first == null || second == null) {
1✔
1227
            return null;
1✔
1228
        }
1229
        return sum(first, second).doubleValue() / 2;
1✔
1230
    }
1231

1232
    public static Double average(Integer first, Integer second) {
1233
        if (first == null || second == null) {
1✔
1234
            return null;
1✔
1235
        }
1236
        return sum(first, second).doubleValue() / 2;
1✔
1237
    }
1238

1239
    public static Double average(Long first, Long second) {
1240
        if (first == null || second == null) {
1✔
1241
            return null;
1✔
1242
        }
1243
        return sum(first, second).doubleValue() / 2;
1✔
1244
    }
1245

1246
    public static <T extends Number> T sum(final Iterable<T> iterable) {
1247
        T result = null;
1✔
1248
        for (final T item : iterable) {
1✔
1249
            result = add(result, item);
1✔
1250
        }
1✔
1251
        return result;
1✔
1252
    }
1253

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

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

1271
    @SuppressWarnings("unchecked")
1272
    public <F extends Number> F sum() {
1273
        return sum((List<F>) getIterable());
1✔
1274
    }
1275

1276
    @SuppressWarnings("unchecked")
1277
    public <E, F extends Number> F sum(final Function<E, F> func) {
1278
        return sum((List<E>) getIterable(), func);
1✔
1279
    }
1280

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

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

1314
    private static java.math.BigInteger sum(
1315
            java.math.BigInteger first, java.math.BigInteger second) {
1316
        return first.add(second);
1✔
1317
    }
1318

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

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

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

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

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

1339
    private static Short sum(Short first, Short second) {
1340
        return (short) (first + second);
1✔
1341
    }
1342

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

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

1389
    @SuppressWarnings("unchecked")
1390
    public double mean() {
1391
        return mean((Iterable<Number>) getIterable());
1✔
1392
    }
1393

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

1407
    @SuppressWarnings("unchecked")
1408
    public double median() {
1409
        return median((Iterable<Number>) getIterable());
1✔
1410
    }
1411

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

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

1431
    public static String upperFirst(final String string) {
1432
        return createCaseFirst("toUpperCase").apply(string);
1✔
1433
    }
1434

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

1439
    public static String uncapitalize(final String string) {
1440
        return lowerFirst(baseToString(string));
1✔
1441
    }
1442

1443
    private static String baseToString(String value) {
1444
        return value == null ? "" : value;
1✔
1445
    }
1446

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

1460
    public static List<String> words(final String string) {
1461
        final String localString = baseToString(string);
1✔
1462
        final List<String> result = new ArrayList<>();
1✔
1463
        final java.util.regex.Matcher matcher = reWords.matcher(localString);
1✔
1464
        while (matcher.find()) {
1✔
1465
            result.add(matcher.group());
1✔
1466
        }
1467
        return result;
1✔
1468
    }
1469

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

1478
            while (++index < length) {
1✔
1479
                result = callback.apply(result, array.get(index), index);
1✔
1480
            }
1481
            return result;
1✔
1482
        };
1483
    }
1484

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

1494
    public static boolean endsWith(final String string, final String target) {
1495
        return endsWith(string, target, null);
1✔
1496
    }
1497

1498
    public static boolean endsWith(
1499
            final String string, final String target, final Integer position) {
1500
        if (string == null || target == null) {
1✔
1501
            return false;
1✔
1502
        }
1503
        final String localString = baseToString(string);
1✔
1504

1505
        final int length = localString.length();
1✔
1506
        final int fixedPosition = position == null || position < 0 ? 0 : position;
1✔
1507
        final int localPosition = position == null ? length : Math.min(fixedPosition, length);
1✔
1508

1509
        final int localPosition2 = localPosition - target.length();
1✔
1510
        return localPosition2 >= 0 && localString.indexOf(target, localPosition2) == localPosition2;
1✔
1511
    }
1512

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

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

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

1547
    public static String pad(final String string, final int length) {
1548
        return pad(string, length, null);
1✔
1549
    }
1550

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

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

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

1578
    public static String padStart(final String string, final Integer length, final String chars) {
1579
        return createPadDir(false).apply(string, length, chars);
1✔
1580
    }
1581

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

1586
    public static String padEnd(final String string, final Integer length, final String chars) {
1587
        return createPadDir(true).apply(string, length, chars);
1✔
1588
    }
1589

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

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

1609
    public static boolean startsWith(final String string, final String target) {
1610
        return startsWith(string, target, null);
1✔
1611
    }
1612

1613
    public static boolean startsWith(
1614
            final String string, final String target, final Integer position) {
1615
        if (string == null || target == null) {
1✔
1616
            return false;
1✔
1617
        }
1618
        final String localString = baseToString(string);
1✔
1619

1620
        final int length = localString.length();
1✔
1621
        final int localPosition;
1622
        if (position == null) {
1✔
1623
            localPosition = 0;
1✔
1624
        } else {
1625
            final int from = position < 0 ? 0 : position;
1✔
1626
            localPosition = Math.min(from, length);
1✔
1627
        }
1628

1629
        return localString.lastIndexOf(target, localPosition) == localPosition;
1✔
1630
    }
1631

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

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

1649
    public static String trim(final String string) {
1650
        return trim(string, null);
1✔
1651
    }
1652

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

1669
    public static String trimStart(final String string) {
1670
        return trimStart(string, null);
1✔
1671
    }
1672

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

1688
    public static String trimEnd(final String string) {
1689
        return trimEnd(string, null);
1✔
1690
    }
1691

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

1707
    public static String trunc(final String string) {
1708
        return trunc(string, DEFAULT_TRUNC_LENGTH);
1✔
1709
    }
1710

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

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

1731
    private enum OperationType {
1✔
1732
        GET,
1✔
1733
        SET,
1✔
1734
        UPDATE,
1✔
1735
        REMOVE
1✔
1736
    }
1737

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

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

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

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

1807
    private static Map.Entry getMapEntry(Map map) {
1808
        return map.isEmpty() ? null : (Map.Entry) map.entrySet().iterator().next();
1✔
1809
    }
1810

1811
    public static <T> T get(final Map<String, Object> object, final String path) {
1812
        return get(object, stringToPath(path));
1✔
1813
    }
1814

1815
    public static <T> T get(final Map<String, Object> object, final List<String> paths) {
1816
        return baseGetOrSetOrRemove(object, paths, null, OperationType.GET);
1✔
1817
    }
1818

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

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

1853
    public static <T> T set(final Map<String, Object> object, final String path, Object value) {
1854
        return set(object, stringToPath(path), value);
1✔
1855
    }
1856

1857
    public static <T> T set(
1858
            final Map<String, Object> object, final List<String> paths, Object value) {
1859
        return baseGetOrSetOrRemove(object, paths, value, OperationType.SET);
1✔
1860
    }
1861

1862
    public static <T> T update(final Map<String, Object> object, final String path, Object value) {
1863
        return update(object, stringToPath(path), value);
1✔
1864
    }
1865

1866
    public static <T> T update(
1867
            final Map<String, Object> object, final List<String> paths, Object value) {
1868
        return baseGetOrSetOrRemove(object, paths, value, OperationType.UPDATE);
1✔
1869
    }
1870

1871
    public static <T> T remove(final Map<String, Object> object, final String path) {
1872
        return remove(object, stringToPath(path));
1✔
1873
    }
1874

1875
    public static <T> T remove(final Map<String, Object> object, final List<String> paths) {
1876
        return baseGetOrSetOrRemove(object, paths, null, OperationType.REMOVE);
1✔
1877
    }
1878

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

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

1913
    public static Map<String, Object> setValue(
1914
            final Map<String, Object> map, final String key, final Object newValue) {
1915
        return setValue(map, key, (key1, value) -> newValue);
1✔
1916
    }
1917

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

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

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

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

1998
    public static List<Object> merge(List<Object> list1, List<Object> list2) {
1999
        List<Object> outList1 = newArrayList(list1);
1✔
2000
        List<Object> outList2 = newArrayList(list2);
1✔
2001
        outList2.removeAll(list1);
1✔
2002
        outList1.addAll(outList2);
1✔
2003
        return outList1;
1✔
2004
    }
2005

2006
    public static class FetchResponse {
2007
        private final boolean ok;
2008
        private final int status;
2009
        private final Map<String, List<String>> headerFields;
2010
        private final java.io.ByteArrayOutputStream stream;
2011

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

2023
        public boolean isOk() {
2024
            return ok;
1✔
2025
        }
2026

2027
        public int getStatus() {
2028
            return status;
1✔
2029
        }
2030

2031
        public Map<String, List<String>> getHeaderFields() {
2032
            return headerFields;
1✔
2033
        }
2034

2035
        public byte[] blob() {
2036
            return stream.toByteArray();
1✔
2037
        }
2038

2039
        public String text() {
2040
            return stream.toString(StandardCharsets.UTF_8);
1✔
2041
        }
2042

2043
        public Object json() {
2044
            return Json.fromJson(text());
1✔
2045
        }
2046

2047
        public Map<String, Object> jsonMap() {
2048
            return fromJsonMap(text());
1✔
2049
        }
2050

2051
        public Object xml() {
2052
            return Xml.fromXml(text());
1✔
2053
        }
2054

2055
        public Map<String, Object> xmlMap() {
2056
            return fromXmlMap(text());
1✔
2057
        }
2058
    }
2059

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

2069
    public static void decompressGzip(final String sourceFileName, final String targetFileName)
2070
            throws IOException {
2071
        try (GZIPInputStream gis =
1✔
2072
                new GZIPInputStream(new FileInputStream(new File(sourceFileName)))) {
2073
            Files.copy(gis, Paths.get(targetFileName));
1✔
2074
        }
2075
    }
1✔
2076

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

2081
    public static FetchResponse fetch(
2082
            final String url, final Integer connectTimeout, final Integer readTimeout) {
2083
        return fetch(url, null, null, DEFAULT_HEADER_FIELDS, connectTimeout, readTimeout);
1✔
2084
    }
2085

2086
    public static FetchResponse fetch(
2087
            final String url,
2088
            final Integer connectTimeout,
2089
            final Integer readTimeout,
2090
            final Integer retryCount,
2091
            final Integer timeBetweenRetry) {
2092
        return Fetch.fetch(
1✔
2093
                url,
2094
                null,
2095
                null,
2096
                DEFAULT_HEADER_FIELDS,
2097
                connectTimeout,
2098
                readTimeout,
2099
                retryCount,
2100
                timeBetweenRetry);
2101
    }
2102

2103
    public static FetchResponse fetch(final String url, final String method, final String body) {
2104
        return fetch(url, method, body, DEFAULT_HEADER_FIELDS, null, null);
1✔
2105
    }
2106

2107
    public static class BaseHttpSslSocketFactory extends javax.net.ssl.SSLSocketFactory {
2108
        private javax.net.ssl.SSLContext getSslContext() {
2109
            return createEasySslContext();
2110
        }
2111

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

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

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

2132
        @Override
2133
        public java.net.Socket createSocket(String arg0, int arg1) throws java.io.IOException {
2134
            return getSslContext().getSocketFactory().createSocket(arg0, arg1);
2135
        }
2136

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

2142
        @Override
2143
        public String[] getDefaultCipherSuites() {
2144
            return new String[] {};
2145
        }
2146

2147
        @Override
2148
        public java.net.Socket createSocket(
2149
                java.net.Socket arg0, String arg1, int arg2, boolean arg3)
2150
                throws java.io.IOException {
2151
            return getSslContext().getSocketFactory().createSocket(arg0, arg1, arg2, arg3);
2152
        }
2153

2154
        private javax.net.ssl.SSLContext createEasySslContext() {
2155
            try {
2156
                javax.net.ssl.SSLContext context = javax.net.ssl.SSLContext.getInstance("SSL");
2157
                context.init(
2158
                        null, new javax.net.ssl.TrustManager[] {MyX509TrustManager.manger}, null);
2159
                return context;
2160
            } catch (Exception ex) {
2161
                throw new UnsupportedOperationException(ex);
2162
            }
2163
        }
2164

2165
        public static class MyX509TrustManager implements javax.net.ssl.X509TrustManager {
2166

2167
            static MyX509TrustManager manger = new MyX509TrustManager();
2168

2169
            public MyX509TrustManager() {
2170
                // ignore MyX509TrustManager
2171
            }
2172

2173
            public java.security.cert.X509Certificate[] getAcceptedIssuers() {
2174
                return new java.security.cert.X509Certificate[] {};
2175
            }
2176

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

2182
            public void checkServerTrusted(
2183
                    java.security.cert.X509Certificate[] chain, String authType) {
2184
                // ignore checkServerTrusted
2185
            }
2186
        }
2187
    }
2188

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

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

2263
    public static class Fetch {
2264
        private Fetch() {}
2265

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

2315
    public static List<String> explode(final String input) {
2316
        List<String> result = new ArrayList<>();
1✔
2317
        if (isNull(input)) {
1✔
2318
            return result;
1✔
2319
        }
2320
        for (char character : input.toCharArray()) {
1✔
2321
            result.add(String.valueOf(character));
1✔
2322
        }
2323
        return result;
1✔
2324
    }
2325

2326
    public static String implode(final String[] input) {
2327
        StringBuilder builder = new StringBuilder();
1✔
2328
        for (String character : input) {
1✔
2329
            if (nonNull(character)) {
1✔
2330
                builder.append(character);
1✔
2331
            }
2332
        }
2333
        return builder.toString();
1✔
2334
    }
2335

2336
    public static String implode(final Iterable<String> input) {
2337
        StringBuilder builder = new StringBuilder();
1✔
2338
        for (String character : input) {
1✔
2339
            if (nonNull(character)) {
1✔
2340
                builder.append(character);
1✔
2341
            }
2342
        }
1✔
2343
        return builder.toString();
1✔
2344
    }
2345

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

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

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

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

2362
    public String deburr() {
2363
        return deburr(getString().get());
1✔
2364
    }
2365

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

2370
    public boolean endsWith(final String target, final Integer position) {
2371
        return endsWith(getString().get(), target, position);
1✔
2372
    }
2373

2374
    public String kebabCase() {
2375
        return kebabCase(getString().get());
1✔
2376
    }
2377

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

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

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

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

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

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

2402
    public String padEnd(final int length, final String chars) {
2403
        return padEnd(getString().get(), length, chars);
1✔
2404
    }
2405

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

2410
    public String startCase() {
2411
        return startCase(getString().get());
1✔
2412
    }
2413

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

2418
    public boolean startsWith(final String target, final Integer position) {
2419
        return startsWith(getString().get(), target, position);
1✔
2420
    }
2421

2422
    public String trim() {
2423
        return trim(getString().get());
1✔
2424
    }
2425

2426
    public String trimWith(final String chars) {
2427
        return trim(getString().get(), chars);
1✔
2428
    }
2429

2430
    public String trimStart() {
2431
        return trimStart(getString().get());
1✔
2432
    }
2433

2434
    public String trimStartWith(final String chars) {
2435
        return trimStart(getString().get(), chars);
1✔
2436
    }
2437

2438
    public String trimEnd() {
2439
        return trimEnd(getString().get());
1✔
2440
    }
2441

2442
    public String trimEndWith(final String chars) {
2443
        return trimEnd(getString().get(), chars);
1✔
2444
    }
2445

2446
    public String trunc() {
2447
        return trunc(getString().get());
1✔
2448
    }
2449

2450
    public String trunc(final int length) {
2451
        return trunc(getString().get(), length);
1✔
2452
    }
2453

2454
    public String uncapitalize() {
2455
        return uncapitalize(getString().get());
1✔
2456
    }
2457

2458
    public List<String> words() {
2459
        return words(getString().get());
1✔
2460
    }
2461

2462
    public static class LruCache<K, V> {
2463
        private static final boolean SORT_BY_ACCESS = true;
2464
        private static final float LOAD_FACTOR = 0.75F;
2465
        private final Map<K, V> lruCacheMap;
2466
        private final int capacity;
2467

2468
        public LruCache(int capacity) {
1✔
2469
            this.capacity = capacity;
1✔
2470
            this.lruCacheMap = new LinkedHashMap<>(capacity, LOAD_FACTOR, SORT_BY_ACCESS);
1✔
2471
        }
1✔
2472

2473
        public V get(K key) {
2474
            return lruCacheMap.get(key);
1✔
2475
        }
2476

2477
        public void put(K key, V value) {
2478
            if (lruCacheMap.containsKey(key)) {
1✔
2479
                lruCacheMap.remove(key);
1✔
2480
            } else if (lruCacheMap.size() >= capacity) {
1✔
2481
                lruCacheMap.remove(lruCacheMap.keySet().iterator().next());
1✔
2482
            }
2483
            lruCacheMap.put(key, value);
1✔
2484
        }
1✔
2485
    }
2486

2487
    public static <K, V> LruCache<K, V> createLruCache(final int capacity) {
2488
        return new LruCache<>(capacity);
1✔
2489
    }
2490

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

2514
    public List<List<T>> createPermutationWithRepetition(final int permutationLength) {
2515
        return createPermutationWithRepetition((List<T>) value(), permutationLength);
1✔
2516
    }
2517

2518
    protected static <T> List<T> newArrayList(final Iterable<T> iterable) {
2519
        return Underscore.newArrayList(iterable);
1✔
2520
    }
2521

2522
    public static <T> String join(final Iterable<T> iterable, final String separator) {
2523
        return Underscore.join(iterable, separator);
1✔
2524
    }
2525

2526
    public static String toJson(Collection collection) {
2527
        return Json.toJson(collection);
1✔
2528
    }
2529

2530
    public static String toJson(Map map) {
2531
        return Json.toJson(map);
1✔
2532
    }
2533

2534
    public String toJson() {
2535
        return Json.toJson((Collection) getIterable());
1✔
2536
    }
2537

2538
    @SuppressWarnings("unchecked")
2539
    public static <T> T fromXml(final String xml) {
2540
        return (T) Xml.fromXml(xml);
1✔
2541
    }
2542

2543
    public static Map<String, Object> fromXmlMap(final String xml) {
2544
        return fromXmlMap(xml, Xml.FromType.FOR_CONVERT);
1✔
2545
    }
2546

2547
    public static Map<String, Object> fromXmlMap(final String xml, final Xml.FromType fromType) {
2548
        final Object object = Xml.fromXml(xml, fromType);
1✔
2549
        return getStringObjectMap(object);
1✔
2550
    }
2551

2552
    @SuppressWarnings("unchecked")
2553
    public static <T> T fromXml(final String xml, final Xml.FromType fromType) {
2554
        return (T) Xml.fromXml(xml, fromType);
1✔
2555
    }
2556

2557
    @SuppressWarnings("unchecked")
2558
    public static <T> T fromXmlMakeArrays(final String xml) {
2559
        return (T) Xml.fromXmlMakeArrays(xml);
1✔
2560
    }
2561

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

2567
    public static Map<String, Object> fromXmlWithoutNamespacesMap(final String xml) {
2568
        final Object object = Xml.fromXmlWithoutNamespaces(xml);
1✔
2569
        return getStringObjectMap(object);
1✔
2570
    }
2571

2572
    @SuppressWarnings("unchecked")
2573
    public static <T> T fromXmlWithoutAttributes(final String xml) {
2574
        return (T) Xml.fromXmlWithoutAttributes(xml);
1✔
2575
    }
2576

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

2582
    public static String toXml(Collection collection) {
2583
        return Xml.toXml(collection);
1✔
2584
    }
2585

2586
    public static String toXml(Map map) {
2587
        return Xml.toXml(map);
1✔
2588
    }
2589

2590
    @SuppressWarnings("unchecked")
2591
    public static <T> T fromJson(String string) {
2592
        return (T) Json.fromJson(string);
1✔
2593
    }
2594

2595
    public Object fromJson() {
2596
        return Json.fromJson(getString().get());
1✔
2597
    }
2598

2599
    public static Map<String, Object> fromJsonMap(final String string) {
2600
        final Object object = Json.fromJson(string);
1✔
2601
        return getStringObjectMap(object);
1✔
2602
    }
2603

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

2609
    @SuppressWarnings("unchecked")
2610
    private static Map<String, Object> getStringObjectMap(Object object) {
2611
        final Map<String, Object> result;
2612
        if (object instanceof Map) {
1✔
2613
            result = (Map<String, Object>) object;
1✔
2614
        } else {
2615
            result = new LinkedHashMap<>();
1✔
2616
            result.put("value", object);
1✔
2617
        }
2618
        return result;
1✔
2619
    }
2620

2621
    public String toXml() {
2622
        return Xml.toXml((Collection) getIterable());
1✔
2623
    }
2624

2625
    public Object fromXml() {
2626
        return Xml.fromXml(getString().get());
1✔
2627
    }
2628

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

2672
    public static String jsonToXml(String json, Xml.XmlStringBuilder.Step identStep) {
2673
        return jsonToXml(json, identStep, null, ROOT);
1✔
2674
    }
2675

2676
    public static String jsonToXml(String json, JsonToXmlMode mode) {
2677
        return jsonToXml(json, Xml.XmlStringBuilder.Step.TWO_SPACES, mode, ROOT);
1✔
2678
    }
2679

2680
    public static String jsonToXml(String json, JsonToXmlMode mode, String newRootName) {
2681
        return jsonToXml(json, Xml.XmlStringBuilder.Step.TWO_SPACES, mode, newRootName);
1✔
2682
    }
2683

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

2692
    public static String jsonToXml(String json) {
2693
        return jsonToXml(json, Xml.XmlStringBuilder.Step.TWO_SPACES, null, null);
1✔
2694
    }
2695

2696
    @SuppressWarnings("unchecked")
2697
    public static String xmlToJson(
2698
            String xml, Json.JsonStringBuilder.Step identStep, XmlToJsonMode mode) {
2699
        Object object = Xml.fromXml(xml);
1✔
2700
        final String result;
2701
        if (object instanceof Map) {
1✔
2702
            if (mode == XmlToJsonMode.REPLACE_SELF_CLOSING_WITH_NULL) {
1✔
2703
                result = Json.toJson(replaceSelfClosingWithNull((Map) object), identStep);
1✔
2704
            } else if (mode == XmlToJsonMode.REPLACE_SELF_CLOSING_WITH_STRING) {
1✔
2705
                result = Json.toJson(replaceSelfClosingWithEmpty((Map) object), identStep);
1✔
2706
            } else if (mode == XmlToJsonMode.REPLACE_EMPTY_VALUE_WITH_NULL) {
1✔
2707
                result = Json.toJson(replaceEmptyValueWithNull((Map) object), identStep);
1✔
2708
            } else if (mode == XmlToJsonMode.REPLACE_MINUS_WITH_AT) {
1✔
2709
                result = Json.toJson(replaceMinusWithAt((Map) object), identStep);
1✔
2710
            } else if (mode == XmlToJsonMode.REPLACE_EMPTY_TAG_WITH_NULL_AND_MINUS_WITH_AT) {
1✔
2711
                result =
1✔
2712
                        Json.toJson(
1✔
2713
                                replaceMinusWithAt(
1✔
2714
                                        replaceEmptyValueWithNull(
1✔
2715
                                                replaceSelfClosingWithNull((Map) object))),
1✔
2716
                                identStep);
2717
            } else if (mode == XmlToJsonMode.REPLACE_EMPTY_TAG_WITH_NULL) {
1✔
2718
                result =
1✔
2719
                        Json.toJson(
1✔
2720
                                replaceEmptyValueWithNull(replaceSelfClosingWithNull((Map) object)),
1✔
2721
                                identStep);
2722
            } else if (mode == XmlToJsonMode.REPLACE_EMPTY_TAG_WITH_STRING) {
1✔
2723
                result =
1✔
2724
                        Json.toJson(
1✔
2725
                                (Map<String, Object>)
2726
                                        replaceEmptyValueWithEmptyString(
1✔
2727
                                                replaceSelfClosingWithEmpty((Map) object)),
1✔
2728
                                identStep);
2729
            } else if (mode == XmlToJsonMode.REMOVE_FIRST_LEVEL) {
1✔
2730
                result = Json.toJson(replaceFirstLevel((Map) object), identStep);
1✔
2731
            } else if (mode == XmlToJsonMode.WITHOUT_NAMESPACES) {
1✔
2732
                result = Json.toJson((Map) Xml.fromXmlWithoutNamespaces(xml), identStep);
1✔
2733
            } else {
2734
                result = Json.toJson((Map) object, identStep);
1✔
2735
            }
2736
            return result;
1✔
2737
        }
2738
        return Json.toJson((List) object, identStep);
1✔
2739
    }
2740

2741
    public static String xmlToJson(String xml) {
2742
        return xmlToJson(xml, Json.JsonStringBuilder.Step.TWO_SPACES, null);
1✔
2743
    }
2744

2745
    public static String xmlToJson(String xml, Json.JsonStringBuilder.Step identStep) {
2746
        return xmlToJson(xml, identStep, null);
1✔
2747
    }
2748

2749
    public static String xmlToJson(String xml, XmlToJsonMode mode) {
2750
        return xmlToJson(xml, Json.JsonStringBuilder.Step.TWO_SPACES, mode);
1✔
2751
    }
2752

2753
    public static String xmlOrJsonToJson(String xmlOrJson, Json.JsonStringBuilder.Step identStep) {
2754
        TextType textType = getTextType(xmlOrJson);
1✔
2755
        final String result;
2756
        if (textType == TextType.JSON) {
1✔
2757
            result = getJsonString(identStep, fromJson(xmlOrJson));
1✔
2758
        } else if (textType == TextType.XML) {
1✔
2759
            result = getJsonString(identStep, fromXml(xmlOrJson));
1✔
2760
        } else {
2761
            result = xmlOrJson;
1✔
2762
        }
2763
        return result;
1✔
2764
    }
2765

2766
    public static String xmlOrJsonToJson(String xmlOrJson) {
2767
        return xmlOrJsonToJson(xmlOrJson, Json.JsonStringBuilder.Step.TWO_SPACES);
1✔
2768
    }
2769

2770
    @SuppressWarnings("unchecked")
2771
    private static String getJsonString(Json.JsonStringBuilder.Step identStep, Object object) {
2772
        final String result;
2773
        if (object instanceof Map) {
1✔
2774
            result = Json.toJson((Map) object, identStep);
1✔
2775
        } else {
2776
            result = Json.toJson((List) object, identStep);
1✔
2777
        }
2778
        return result;
1✔
2779
    }
2780

2781
    public static String xmlOrJsonToXml(String xmlOrJson, Xml.XmlStringBuilder.Step identStep) {
2782
        TextType textType = getTextType(xmlOrJson);
1✔
2783
        final String result;
2784
        if (textType == TextType.JSON) {
1✔
2785
            result = getXmlString(identStep, fromJson(xmlOrJson));
1✔
2786
        } else if (textType == TextType.XML) {
1✔
2787
            result = getXmlString(identStep, fromXml(xmlOrJson));
1✔
2788
        } else {
2789
            result = xmlOrJson;
1✔
2790
        }
2791
        return result;
1✔
2792
    }
2793

2794
    public static String xmlOrJsonToXml(String xmlOrJson) {
2795
        return xmlOrJsonToXml(xmlOrJson, Xml.XmlStringBuilder.Step.TWO_SPACES);
1✔
2796
    }
2797

2798
    @SuppressWarnings("unchecked")
2799
    private static String getXmlString(Xml.XmlStringBuilder.Step identStep, Object object) {
2800
        final String result;
2801
        if (object instanceof Map) {
1✔
2802
            result = Xml.toXml((Map) object, identStep);
1✔
2803
        } else {
2804
            result = Xml.toXml((List) object, identStep);
1✔
2805
        }
2806
        return result;
1✔
2807
    }
2808

2809
    public enum TextType {
1✔
2810
        JSON,
1✔
2811
        XML,
1✔
2812
        OTHER
1✔
2813
    }
2814

2815
    public static TextType getTextType(String text) {
2816
        String trimmed = trim(text);
1✔
2817
        final TextType textType;
2818
        if (trimmed.startsWith("{") && trimmed.endsWith("}")
1✔
2819
                || trimmed.startsWith("[") && trimmed.endsWith("]")) {
1✔
2820
            textType = TextType.JSON;
1✔
2821
        } else if (trimmed.startsWith("<") && trimmed.endsWith(">")) {
1✔
2822
            textType = TextType.XML;
1✔
2823
        } else {
2824
            textType = TextType.OTHER;
1✔
2825
        }
2826
        return textType;
1✔
2827
    }
2828

2829
    public static String formatJsonOrXml(String jsonOrXml, String identStep) {
2830
        TextType textType = getTextType(jsonOrXml);
1✔
2831
        final String result;
2832
        if (textType == TextType.JSON) {
1✔
2833
            result = formatJson(jsonOrXml, Json.JsonStringBuilder.Step.valueOf(identStep));
1✔
2834
        } else if (textType == TextType.XML) {
1✔
2835
            result = formatXml(jsonOrXml, Xml.XmlStringBuilder.Step.valueOf(identStep));
1✔
2836
        } else {
2837
            result = jsonOrXml;
1✔
2838
        }
2839
        return result;
1✔
2840
    }
2841

2842
    public static String formatJsonOrXml(String jsonOrXml) {
2843
        return formatJsonOrXml(jsonOrXml, "TWO_SPACES");
1✔
2844
    }
2845

2846
    public static String formatJson(String json, Json.JsonStringBuilder.Step identStep) {
2847
        return Json.formatJson(json, identStep);
1✔
2848
    }
2849

2850
    public static String formatJson(String json) {
2851
        return Json.formatJson(json);
1✔
2852
    }
2853

2854
    public static String formatXml(String xml, Xml.XmlStringBuilder.Step identStep) {
2855
        return Xml.formatXml(xml, identStep);
1✔
2856
    }
2857

2858
    public static String formatXml(String xml) {
2859
        return Xml.formatXml(xml);
1✔
2860
    }
2861

2862
    public static String changeXmlEncoding(
2863
            String xml, Xml.XmlStringBuilder.Step identStep, String encoding) {
2864
        return Xml.changeXmlEncoding(xml, identStep, encoding);
1✔
2865
    }
2866

2867
    public static String changeXmlEncoding(String xml, String encoding) {
2868
        return Xml.changeXmlEncoding(xml, encoding);
1✔
2869
    }
2870

2871
    public static Map<String, Object> removeMinusesAndConvertNumbers(Map<String, Object> map) {
2872
        Map<String, Object> outMap = new LinkedHashMap<>();
1✔
2873
        for (Map.Entry<String, Object> entry : map.entrySet()) {
1✔
2874
            final String newKey;
2875
            if (entry.getKey().startsWith("-")) {
1✔
2876
                newKey = entry.getKey().substring(1);
1✔
2877
            } else {
2878
                newKey = entry.getKey();
1✔
2879
            }
2880
            if (!entry.getKey().equals(selfClosing)
1✔
2881
                    && !entry.getKey().equals("#omit-xml-declaration")) {
1✔
2882
                outMap.put(newKey, makeObject(entry.getValue()));
1✔
2883
            }
2884
        }
1✔
2885
        return outMap;
1✔
2886
    }
2887

2888
    @SuppressWarnings("unchecked")
2889
    private static Object makeObject(Object value) {
2890
        final Object result;
2891
        if (value instanceof List) {
1✔
2892
            List<Object> values = new ArrayList<>();
1✔
2893
            for (Object item : (List) value) {
1✔
2894
                values.add(
1✔
2895
                        item instanceof Map
1✔
2896
                                ? removeMinusesAndConvertNumbers((Map<String, Object>) item)
1✔
2897
                                : item);
1✔
2898
            }
1✔
2899
            result = values;
1✔
2900
        } else if (value instanceof Map) {
1✔
2901
            result = removeMinusesAndConvertNumbers((Map) value);
1✔
2902
        } else {
2903
            String stringValue = String.valueOf(value);
1✔
2904
            result = isJsonNumber(stringValue) ? Xml.stringToNumber(stringValue) : value;
1✔
2905
        }
2906
        return result;
1✔
2907
    }
2908

2909
    public static boolean isJsonNumber(final String string) {
2910
        boolean eFound = false;
1✔
2911
        boolean periodValid = true;
1✔
2912
        boolean pmValid = true;
1✔
2913
        boolean numberEncountered = false;
1✔
2914
        for (char ch : string.toCharArray()) {
1✔
2915
            if (pmValid) {
1✔
2916
                pmValid = false;
1✔
2917
                if (ch == '-') {
1✔
2918
                    continue;
1✔
2919
                }
2920
            }
2921
            if (!eFound && (ch == 'e' || ch == 'E')) {
1✔
2922
                eFound = true;
1✔
2923
                periodValid = false;
1✔
2924
                pmValid = true;
1✔
2925
                numberEncountered = false;
1✔
2926
                continue;
1✔
2927
            }
2928
            if (periodValid && ch == '.') {
1✔
2929
                periodValid = false;
1✔
2930
                continue;
1✔
2931
            }
2932
            if (ch < '0' || ch > '9') {
1✔
2933
                return false;
1✔
2934
            }
2935
            numberEncountered = true;
1✔
2936
        }
2937
        return numberEncountered;
1✔
2938
    }
2939

2940
    @SuppressWarnings("unchecked")
2941
    public static Map<String, Object> replaceSelfClosingWithNull(Map<String, Object> map) {
2942
        return (Map<String, Object>) replaceSelfClosingWithValue(map, null);
1✔
2943
    }
2944

2945
    @SuppressWarnings("unchecked")
2946
    public static Map<String, Object> replaceSelfClosingWithEmpty(Map<String, Object> map) {
2947
        Object result = replaceSelfClosingWithValue(map, "");
1✔
2948
        if (result instanceof Map) {
1✔
2949
            return (Map<String, Object>) result;
1✔
2950
        }
2951
        return Collections.emptyMap();
1✔
2952
    }
2953

2954
    @SuppressWarnings("unchecked")
2955
    public static Object replaceSelfClosingWithValue(Map<String, Object> map, String value) {
2956
        Object outMap = new LinkedHashMap<>();
1✔
2957
        for (Map.Entry<String, Object> entry : map.entrySet()) {
1✔
2958
            if (selfClosing.equals(entry.getKey()) && "true".equals(entry.getValue())) {
1✔
2959
                if (map.size() == 1) {
1✔
2960
                    outMap = value;
1✔
2961
                    break;
1✔
2962
                }
2963
            } else {
2964
                ((Map<String, Object>) outMap)
1✔
2965
                        .put(
1✔
2966
                                String.valueOf(entry.getKey()),
1✔
2967
                                makeObjectSelfClose(entry.getValue(), value));
1✔
2968
            }
2969
        }
1✔
2970
        return outMap;
1✔
2971
    }
2972

2973
    @SuppressWarnings("unchecked")
2974
    private static Object makeObjectSelfClose(Object value, String newValue) {
2975
        final Object result;
2976
        if (value instanceof List) {
1✔
2977
            List<Object> values = new ArrayList<>();
1✔
2978
            for (Object item : (List) value) {
1✔
2979
                values.add(
1✔
2980
                        item instanceof Map
1✔
2981
                                ? replaceSelfClosingWithValue((Map) item, newValue)
1✔
2982
                                : item);
1✔
2983
            }
1✔
2984
            result = values;
1✔
2985
        } else if (value instanceof Map) {
1✔
2986
            result = replaceSelfClosingWithValue((Map) value, newValue);
1✔
2987
        } else {
2988
            result = value;
1✔
2989
        }
2990
        return result;
1✔
2991
    }
2992

2993
    public static Map<String, Object> replaceMinusWithAt(Map<String, Object> map) {
2994
        if (map == null) {
1✔
2995
            return null;
1✔
2996
        }
2997
        Map<String, Object> outMap = new LinkedHashMap<>();
1✔
2998
        for (Map.Entry<String, Object> entry : map.entrySet()) {
1✔
2999
            outMap.put(
1✔
3000
                    String.valueOf(entry.getKey()).startsWith("-")
1✔
3001
                            ? "@" + String.valueOf(entry.getKey()).substring(1)
1✔
3002
                            : String.valueOf(entry.getKey()),
1✔
3003
                    replaceMinusWithAtValue(entry.getValue()));
1✔
3004
        }
1✔
3005
        return outMap;
1✔
3006
    }
3007

3008
    @SuppressWarnings("unchecked")
3009
    private static Object replaceMinusWithAtValue(Object value) {
3010
        final Object result;
3011
        if (value instanceof List) {
1✔
3012
            List<Object> values = new ArrayList<>();
1✔
3013
            for (Object item : (List) value) {
1✔
3014
                values.add(item instanceof Map ? replaceMinusWithAt((Map) item) : item);
1✔
3015
            }
1✔
3016
            result = values;
1✔
3017
        } else if (value instanceof Map) {
1✔
3018
            result = replaceMinusWithAt((Map) value);
1✔
3019
        } else {
3020
            result = value;
1✔
3021
        }
3022
        return result;
1✔
3023
    }
3024

3025
    public static Map<String, Object> replaceEmptyValueWithNull(Map<String, Object> map) {
3026
        if (map == null || map.isEmpty()) {
1✔
3027
            return null;
1✔
3028
        }
3029
        Map<String, Object> outMap = new LinkedHashMap<>();
1✔
3030
        for (Map.Entry<String, Object> entry : map.entrySet()) {
1✔
3031
            outMap.put(String.valueOf(entry.getKey()), makeObjectEmptyValue(entry.getValue()));
1✔
3032
        }
1✔
3033
        return outMap;
1✔
3034
    }
3035

3036
    @SuppressWarnings("unchecked")
3037
    private static Object makeObjectEmptyValue(Object value) {
3038
        final Object result;
3039
        if (value instanceof List) {
1✔
3040
            List<Object> values = new ArrayList<>();
1✔
3041
            for (Object item : (List) value) {
1✔
3042
                values.add(item instanceof Map ? replaceEmptyValueWithNull((Map) item) : item);
1✔
3043
            }
1✔
3044
            result = values;
1✔
3045
        } else if (value instanceof Map) {
1✔
3046
            result = replaceEmptyValueWithNull((Map) value);
1✔
3047
        } else {
3048
            result = value;
1✔
3049
        }
3050
        return result;
1✔
3051
    }
3052

3053
    public static Object replaceEmptyValueWithEmptyString(Map<String, Object> map) {
3054
        if (map.isEmpty()) {
1✔
3055
            return "";
1✔
3056
        }
3057
        Map<String, Object> outMap = new LinkedHashMap<>();
1✔
3058
        for (Map.Entry<String, Object> entry : map.entrySet()) {
1✔
3059
            outMap.put(String.valueOf(entry.getKey()), makeObjectEmptyString(entry.getValue()));
1✔
3060
        }
1✔
3061
        return outMap;
1✔
3062
    }
3063

3064
    @SuppressWarnings("unchecked")
3065
    private static Object makeObjectEmptyString(Object value) {
3066
        final Object result;
3067
        if (value instanceof List) {
1✔
3068
            List<Object> values = new ArrayList<>();
1✔
3069
            for (Object item : (List) value) {
1✔
3070
                values.add(
1✔
3071
                        item instanceof Map ? replaceEmptyValueWithEmptyString((Map) item) : item);
1✔
3072
            }
1✔
3073
            result = values;
1✔
3074
        } else if (value instanceof Map) {
1✔
3075
            result = replaceEmptyValueWithEmptyString((Map) value);
1✔
3076
        } else {
3077
            result = value;
1✔
3078
        }
3079
        return result;
1✔
3080
    }
3081

3082
    public static Map<String, Object> forceAttributeUsage(Map<String, Object> map) {
3083
        Map<String, Object> outMap = new LinkedHashMap<>();
1✔
3084
        for (Map.Entry<String, Object> entry : map.entrySet()) {
1✔
3085
            outMap.put(
1✔
3086
                    entry.getValue() instanceof Map
1✔
3087
                                    || entry.getValue() instanceof List
1✔
3088
                                    || String.valueOf(entry.getKey()).startsWith("-")
1✔
3089
                            ? String.valueOf(entry.getKey())
1✔
3090
                            : "-" + entry.getKey(),
1✔
3091
                    makeAttributeUsage(entry.getValue()));
1✔
3092
        }
1✔
3093
        return outMap;
1✔
3094
    }
3095

3096
    @SuppressWarnings("unchecked")
3097
    private static Object makeAttributeUsage(Object value) {
3098
        final Object result;
3099
        if (value instanceof List) {
1✔
3100
            List<Object> values = new ArrayList<>();
1✔
3101
            for (Object item : (List) value) {
1✔
3102
                values.add(item instanceof Map ? forceAttributeUsage((Map) item) : item);
1✔
3103
            }
1✔
3104
            result = values;
1✔
3105
        } else if (value instanceof Map) {
1✔
3106
            result = forceAttributeUsage((Map) value);
1✔
3107
        } else {
3108
            result = value;
1✔
3109
        }
3110
        return result;
1✔
3111
    }
3112

3113
    public static Map<String, Object> replaceNullWithEmptyValue(Map<String, Object> map) {
3114
        Map<String, Object> outMap = new LinkedHashMap<>();
1✔
3115
        for (Map.Entry<String, Object> entry : map.entrySet()) {
1✔
3116
            outMap.put(
1✔
3117
                    entry.getKey(),
1✔
3118
                    entry.getValue() == null
1✔
3119
                            ? new LinkedHashMap<>()
1✔
3120
                            : makeReplaceNullValue(entry.getValue()));
1✔
3121
        }
1✔
3122
        return outMap;
1✔
3123
    }
3124

3125
    @SuppressWarnings("unchecked")
3126
    private static Object makeReplaceNullValue(Object value) {
3127
        final Object result;
3128
        if (value instanceof List) {
1✔
3129
            List<Object> values = new ArrayList<>();
1✔
3130
            for (Object item : (List) value) {
1✔
3131
                values.add(item instanceof Map ? replaceNullWithEmptyValue((Map) item) : item);
1✔
3132
            }
1✔
3133
            result = values;
1✔
3134
        } else if (value instanceof Map) {
1✔
3135
            result = replaceNullWithEmptyValue((Map) value);
1✔
3136
        } else {
3137
            result = value;
1✔
3138
        }
3139
        return result;
1✔
3140
    }
3141

3142
    public static Map<String, Object> replaceEmptyStringWithEmptyValue(Map<String, Object> map) {
3143
        Map<String, Object> outMap = new LinkedHashMap<>();
1✔
3144
        for (Map.Entry<String, Object> entry : map.entrySet()) {
1✔
3145
            outMap.put(
1✔
3146
                    entry.getKey(),
1✔
3147
                    "".equals(entry.getValue())
1✔
3148
                            ? new LinkedHashMap<>()
1✔
3149
                            : makeReplaceEmptyString(entry.getValue()));
1✔
3150
        }
1✔
3151
        return outMap;
1✔
3152
    }
3153

3154
    @SuppressWarnings("unchecked")
3155
    private static Object makeReplaceEmptyString(Object value) {
3156
        final Object result;
3157
        if (value instanceof List) {
1✔
3158
            List<Object> values = new ArrayList<>();
1✔
3159
            for (Object item : (List) value) {
1✔
3160
                values.add(
1✔
3161
                        item instanceof Map ? replaceEmptyStringWithEmptyValue((Map) item) : item);
1✔
3162
            }
1✔
3163
            result = values;
1✔
3164
        } else if (value instanceof Map) {
1✔
3165
            result = replaceEmptyStringWithEmptyValue((Map) value);
1✔
3166
        } else {
3167
            result = value;
1✔
3168
        }
3169
        return result;
1✔
3170
    }
3171

3172
    public static Map<String, Object> replaceNumberAndBooleanWithString(Map<String, Object> map) {
3173
        Map<String, Object> outMap = new LinkedHashMap<>();
1✔
3174
        for (Map.Entry<String, Object> entry : map.entrySet()) {
1✔
3175
            outMap.put(
1✔
3176
                    entry.getKey(),
1✔
3177
                    entry.getValue() instanceof Boolean || entry.getValue() instanceof Number
1✔
3178
                            ? String.valueOf(entry.getValue())
1✔
3179
                            : makeReplaceNumberAndBoolean(entry.getValue()));
1✔
3180
        }
1✔
3181
        return outMap;
1✔
3182
    }
3183

3184
    @SuppressWarnings("unchecked")
3185
    private static Object makeReplaceNumberAndBoolean(Object value) {
3186
        final Object result;
3187
        if (value instanceof List) {
1✔
3188
            List<Object> values = new ArrayList<>();
1✔
3189
            for (Object item : (List) value) {
1✔
3190
                if (item instanceof Map) {
1✔
3191
                    values.add(replaceNumberAndBooleanWithString((Map) item));
1✔
3192
                } else if (item instanceof Number || item instanceof Boolean || isNull(item)) {
1✔
3193
                    values.add(String.valueOf(item));
1✔
3194
                } else {
3195
                    values.add(item);
1✔
3196
                }
3197
            }
1✔
3198
            result = values;
1✔
3199
        } else if (value instanceof Map) {
1✔
3200
            result = replaceNumberAndBooleanWithString((Map) value);
1✔
3201
        } else if (isNull(value)) {
1✔
3202
            result = "null";
1✔
3203
        } else {
3204
            result = value;
1✔
3205
        }
3206
        return result;
1✔
3207
    }
3208

3209
    public static Map<String, Object> replaceFirstLevel(Map<String, Object> map) {
3210
        return replaceFirstLevel(map, 0);
1✔
3211
    }
3212

3213
    @SuppressWarnings("unchecked")
3214
    public static Map<String, Object> replaceFirstLevel(Map<String, Object> map, int level) {
3215
        Map<String, Object> outMap = new LinkedHashMap<>();
1✔
3216
        for (Map.Entry<String, Object> entry : map.entrySet()) {
1✔
3217
            outMap.put(entry.getKey(), makeReplaceFirstLevel(entry.getValue(), level + 1));
1✔
3218
        }
1✔
3219
        if (level == 0 && Xml.XmlValue.getMapValue(outMap) instanceof Map) {
1✔
3220
            Map<String, Object> outMap2 = (Map<String, Object>) Xml.XmlValue.getMapValue(outMap);
1✔
3221
            if (selfClosing.equals(Xml.XmlValue.getMapKey(outMap2))
1✔
3222
                    && "true".equals(Xml.XmlValue.getMapValue(outMap2))) {
1✔
3223
                outMap2.remove(selfClosing);
1✔
3224
            }
3225
            return outMap2;
1✔
3226
        }
3227
        return outMap;
1✔
3228
    }
3229

3230
    @SuppressWarnings("unchecked")
3231
    private static Object makeReplaceFirstLevel(Object value, int level) {
3232
        final Object result;
3233
        if (value instanceof List) {
1✔
3234
            List<Object> values = new ArrayList<>();
1✔
3235
            for (Object item : (List) value) {
1✔
3236
                values.add(item instanceof Map ? replaceFirstLevel((Map) item, level + 1) : item);
1✔
3237
            }
1✔
3238
            result = values;
1✔
3239
        } else if (value instanceof Map) {
1✔
3240
            result = replaceFirstLevel((Map) value, level + 1);
1✔
3241
        } else {
3242
            result = value;
1✔
3243
        }
3244
        return result;
1✔
3245
    }
3246

3247
    public static Map<String, Object> replaceNilWithNull(Map<String, Object> map) {
3248
        Map<String, Object> outMap = new LinkedHashMap<>();
1✔
3249
        for (Map.Entry<String, Object> entry : map.entrySet()) {
1✔
3250
            Object outValue = makeReplaceNilWithNull(entry.getValue());
1✔
3251
            if (outValue instanceof Map
1✔
3252
                    && (nilKey.equals(Xml.XmlValue.getMapKey(outValue))
1✔
3253
                            || Xml.XmlValue.getMapKey(outValue).endsWith(":nil"))
1✔
3254
                    && "true".equals(Xml.XmlValue.getMapValue(outValue))
1✔
3255
                    && ((Map) outValue).containsKey(selfClosing)
1✔
3256
                    && "true".equals(((Map) outValue).get(selfClosing))) {
1✔
3257
                outValue = null;
1✔
3258
            }
3259
            outMap.put(entry.getKey(), outValue);
1✔
3260
        }
1✔
3261
        return outMap;
1✔
3262
    }
3263

3264
    @SuppressWarnings("unchecked")
3265
    private static Object makeReplaceNilWithNull(Object value) {
3266
        final Object result;
3267
        if (value instanceof List) {
1✔
3268
            List<Object> values = new ArrayList<>();
1✔
3269
            for (Object item : (List) value) {
1✔
3270
                values.add(item instanceof Map ? replaceNilWithNull((Map) item) : item);
1✔
3271
            }
1✔
3272
            result = values;
1✔
3273
        } else if (value instanceof Map) {
1✔
3274
            result = replaceNilWithNull((Map) value);
1✔
3275
        } else {
3276
            result = value;
1✔
3277
        }
3278
        return result;
1✔
3279
    }
3280

3281
    public static Map<String, Object> deepCopyMap(Map<String, Object> map) {
3282
        Map<String, Object> outMap = new LinkedHashMap<>();
1✔
3283
        for (Map.Entry<String, Object> entry : map.entrySet()) {
1✔
3284
            outMap.put(entry.getKey(), makeDeepCopyMap(entry.getValue()));
1✔
3285
        }
1✔
3286
        return outMap;
1✔
3287
    }
3288

3289
    @SuppressWarnings("unchecked")
3290
    private static Object makeDeepCopyMap(Object value) {
3291
        final Object result;
3292
        if (value instanceof List) {
1✔
3293
            List<Object> values = new ArrayList<>();
1✔
3294
            for (Object item : (List) value) {
1✔
3295
                values.add(item instanceof Map ? deepCopyMap((Map) item) : item);
1✔
3296
            }
1✔
3297
            result = values;
1✔
3298
        } else if (value instanceof Map) {
1✔
3299
            result = deepCopyMap((Map) value);
1✔
3300
        } else {
3301
            result = value;
1✔
3302
        }
3303
        return result;
1✔
3304
    }
3305

3306
    public static Builder objectBuilder() {
3307
        return new U.Builder();
1✔
3308
    }
3309

3310
    public static class Builder {
3311
        private final Map<String, Object> data;
3312

3313
        public Builder() {
1✔
3314
            data = new LinkedHashMap<>();
1✔
3315
        }
1✔
3316

3317
        public Builder add(final String key, final Object value) {
3318
            data.put(key, value);
1✔
3319
            return this;
1✔
3320
        }
3321

3322
        public Builder add(final Object value) {
3323
            data.put(String.valueOf(data.size()), value);
1✔
3324
            return this;
1✔
3325
        }
3326

3327
        public <T> T get(final String path) {
3328
            return U.get(data, path);
1✔
3329
        }
3330

3331
        public <T> T get(final List<String> paths) {
3332
            return U.get(data, paths);
1✔
3333
        }
3334

3335
        public Builder set(final String path, final Object value) {
3336
            U.set(data, path, value);
1✔
3337
            return this;
1✔
3338
        }
3339

3340
        public Builder set(final List<String> paths, final Object value) {
3341
            U.set(data, paths, value);
1✔
3342
            return this;
1✔
3343
        }
3344

3345
        public Builder remove(final String key) {
3346
            U.remove(data, key);
1✔
3347
            return this;
1✔
3348
        }
3349

3350
        public Builder remove(final List<String> keys) {
3351
            U.remove(data, keys);
1✔
3352
            return this;
1✔
3353
        }
3354

3355
        public Builder clear() {
3356
            data.clear();
1✔
3357
            return this;
1✔
3358
        }
3359

3360
        public boolean isEmpty() {
3361
            return data.isEmpty();
1✔
3362
        }
3363

3364
        public int size() {
3365
            return data.size();
1✔
3366
        }
3367

3368
        public Builder add(final Builder builder) {
3369
            data.put(String.valueOf(data.size()), builder.build());
1✔
3370
            return this;
1✔
3371
        }
3372

3373
        public Builder add(final String key, final ArrayBuilder builder) {
3374
            data.put(key, builder.build());
1✔
3375
            return this;
1✔
3376
        }
3377

3378
        public Builder add(final String key, final Builder builder) {
3379
            data.put(key, builder.build());
1✔
3380
            return this;
1✔
3381
        }
3382

3383
        public Builder add(final Map<String, Object> map) {
3384
            data.putAll(deepCopyMap(map));
1✔
3385
            return this;
1✔
3386
        }
3387

3388
        public Builder update(final Map<String, Object> map) {
3389
            U.update(data, deepCopyMap(map));
1✔
3390
            return this;
1✔
3391
        }
3392

3393
        public Builder addNull(final String key) {
3394
            data.put(key, null);
1✔
3395
            return this;
1✔
3396
        }
3397

3398
        @SuppressWarnings("unchecked")
3399
        public Map<String, Object> build() {
3400
            return (Map<String, Object>) ((LinkedHashMap) data).clone();
1✔
3401
        }
3402

3403
        public String toXml() {
3404
            return Xml.toXml(data);
1✔
3405
        }
3406

3407
        public static Builder fromXml(final String xml) {
3408
            final Builder builder = new Builder();
1✔
3409
            builder.data.putAll(fromXmlMap(xml));
1✔
3410
            return builder;
1✔
3411
        }
3412

3413
        public static Builder fromMap(final Map<String, Object> map) {
3414
            final Builder builder = new Builder();
1✔
3415
            builder.data.putAll(deepCopyMap(map));
1✔
3416
            return builder;
1✔
3417
        }
3418

3419
        public String toJson() {
3420
            return Json.toJson(data);
1✔
3421
        }
3422

3423
        public static Builder fromJson(final String json) {
3424
            final Builder builder = new Builder();
1✔
3425
            builder.data.putAll(fromJsonMap(json));
1✔
3426
            return builder;
1✔
3427
        }
3428

3429
        public Chain<Object> toChain() {
3430
            return new U.Chain<>(data.entrySet());
1✔
3431
        }
3432

3433
        @Override
3434
        public String toString() {
3435
            return data.toString();
1✔
3436
        }
3437
    }
3438

3439
    public static ArrayBuilder arrayBuilder() {
3440
        return new U.ArrayBuilder();
1✔
3441
    }
3442

3443
    public static class ArrayBuilder {
3444
        private final List<Object> data;
3445

3446
        public ArrayBuilder() {
1✔
3447
            data = new ArrayList<>();
1✔
3448
        }
1✔
3449

3450
        public ArrayBuilder add(final Object value) {
3451
            data.add(value);
1✔
3452
            return this;
1✔
3453
        }
3454

3455
        public ArrayBuilder addNull() {
3456
            data.add(null);
1✔
3457
            return this;
1✔
3458
        }
3459

3460
        public <T> T get(final String path) {
3461
            return U.get(U.getStringObjectMap(data), "value." + path);
1✔
3462
        }
3463

3464
        public <T> T get(final List<String> paths) {
3465
            List<String> newPaths = new ArrayList<>();
1✔
3466
            newPaths.add("value");
1✔
3467
            newPaths.addAll(paths);
1✔
3468
            return U.get(U.getStringObjectMap(data), newPaths);
1✔
3469
        }
3470

3471
        public ArrayBuilder set(final int index, final Object value) {
3472
            data.set(index, value);
1✔
3473
            return this;
1✔
3474
        }
3475

3476
        public ArrayBuilder remove(final int index) {
3477
            data.remove(index);
1✔
3478
            return this;
1✔
3479
        }
3480

3481
        public ArrayBuilder clear() {
3482
            data.clear();
1✔
3483
            return this;
1✔
3484
        }
3485

3486
        public boolean isEmpty() {
3487
            return data.isEmpty();
1✔
3488
        }
3489

3490
        public int size() {
3491
            return data.size();
1✔
3492
        }
3493

3494
        public ArrayBuilder add(final ArrayBuilder builder) {
3495
            data.addAll(builder.build());
1✔
3496
            return this;
1✔
3497
        }
3498

3499
        public ArrayBuilder add(final Builder builder) {
3500
            data.add(builder.build());
1✔
3501
            return this;
1✔
3502
        }
3503

3504
        @SuppressWarnings("unchecked")
3505
        public ArrayBuilder merge(final List<Object> list) {
3506
            U.merge(data, (List<Object>) ((ArrayList) list).clone());
1✔
3507
            return this;
1✔
3508
        }
3509

3510
        @SuppressWarnings("unchecked")
3511
        public List<Object> build() {
3512
            return (List<Object>) ((ArrayList) data).clone();
1✔
3513
        }
3514

3515
        public String toXml() {
3516
            return Xml.toXml(data);
1✔
3517
        }
3518

3519
        public static ArrayBuilder fromXml(final String xml) {
3520
            final ArrayBuilder builder = new ArrayBuilder();
1✔
3521
            builder.data.addAll(U.<List<Object>>fromXml(xml));
1✔
3522
            return builder;
1✔
3523
        }
3524

3525
        public String toJson() {
3526
            return Json.toJson(data);
1✔
3527
        }
3528

3529
        public static ArrayBuilder fromJson(final String json) {
3530
            final ArrayBuilder builder = new ArrayBuilder();
1✔
3531
            builder.data.addAll(U.<List<Object>>fromJson(json));
1✔
3532
            return builder;
1✔
3533
        }
3534

3535
        public Chain<Object> toChain() {
3536
            return new U.Chain<>(data);
1✔
3537
        }
3538

3539
        @Override
3540
        public String toString() {
3541
            return data.toString();
1✔
3542
        }
3543
    }
3544

3545
    public static Map<String, Object> propertiesToMap(Properties properties) {
3546
        Map<String, Object> map = new LinkedHashMap<>();
1✔
3547
        if (properties != null && !properties.isEmpty()) {
1✔
3548
            Enumeration<?> enumProperties = properties.propertyNames();
1✔
3549
            while (enumProperties.hasMoreElements()) {
1✔
3550
                String name = (String) enumProperties.nextElement();
1✔
3551
                map.put(name, properties.getProperty(name));
1✔
3552
            }
1✔
3553
        }
3554
        return map;
1✔
3555
    }
3556

3557
    public static Properties mapToProperties(Map<String, Object> map) {
3558
        Properties properties = new Properties();
1✔
3559
        if (map != null) {
1✔
3560
            for (final Map.Entry<String, Object> entry : map.entrySet()) {
1✔
3561
                if (!isNull(entry.getValue())) {
1✔
3562
                    properties.put(entry.getKey(), String.valueOf(entry.getValue()));
1✔
3563
                }
3564
            }
1✔
3565
        }
3566
        return properties;
1✔
3567
    }
3568
}
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