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

javadev / underscore-java / #4332

17 Sep 2025 07:13AM UTC coverage: 99.978% (-0.02%) from 100.0%
#4332

push

web-flow
Merge 8fce00752 into 2c08f2fa5

4554 of 4555 relevant lines covered (99.98%)

1.0 hits per line

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

99.94
/src/main/java/com/github/underscore/U.java
1
/*
2
 * The MIT License (MIT)
3
 *
4
 * Copyright 2015-2025 Valentyn Kolesnikov <0009-0003-9608-3364@orcid.org>
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 org.w3c.dom.NodeList;
27

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

69
import javax.xml.xpath.XPath;
70
import javax.xml.xpath.XPathConstants;
71
import javax.xml.xpath.XPathFactory;
72

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

2070
    public static void decompressGzip(final String sourceFileName, final String targetFileName)
2071
            throws IOException {
2072
        try (GZIPInputStream gis = new GZIPInputStream(new FileInputStream(sourceFileName))) {
1✔
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();
×
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 <T> String joinToString(
2527
            final Iterable<T> iterable,
2528
            final String separator,
2529
            final String prefix,
2530
            final String postfix,
2531
            final int limit,
2532
            final String truncated,
2533
            final Function<T, String> transform) {
2534
        return Underscore.joinToString(
1✔
2535
                iterable, separator, prefix, postfix, limit, truncated, transform);
2536
    }
2537

2538
    public static String toJson(Collection collection) {
2539
        return Json.toJson(collection);
1✔
2540
    }
2541

2542
    public static String toJson(Map map) {
2543
        return Json.toJson(map);
1✔
2544
    }
2545

2546
    public String toJson() {
2547
        return Json.toJson((Collection) getIterable());
1✔
2548
    }
2549

2550
    @SuppressWarnings("unchecked")
2551
    public static <T> T fromXml(final String xml) {
2552
        return (T) Xml.fromXml(xml);
1✔
2553
    }
2554

2555
    public static Map<String, Object> fromXmlMap(final String xml) {
2556
        return fromXmlMap(xml, Xml.FromType.FOR_CONVERT);
1✔
2557
    }
2558

2559
    public static Map<String, Object> fromXmlMap(final String xml, final Xml.FromType fromType) {
2560
        final Object object = Xml.fromXml(xml, fromType);
1✔
2561
        return getStringObjectMap(object);
1✔
2562
    }
2563

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

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

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

2579
    public static Map<String, Object> fromXmlWithoutNamespacesMap(final String xml) {
2580
        final Object object = Xml.fromXmlWithoutNamespaces(xml);
1✔
2581
        return getStringObjectMap(object);
1✔
2582
    }
2583

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

2589
    @SuppressWarnings("unchecked")
2590
    public static <T> T fromXmlWithoutNamespacesAndAttributes(final String xml) {
2591
        return (T) Xml.fromXmlWithoutNamespacesAndAttributes(xml);
1✔
2592
    }
2593

2594
    public static String toXml(Collection collection) {
2595
        return Xml.toXml(collection);
1✔
2596
    }
2597

2598
    public static String toXml(Map map) {
2599
        return Xml.toXml(map);
1✔
2600
    }
2601

2602
    @SuppressWarnings("unchecked")
2603
    public static <T> T fromJson(String string) {
2604
        return (T) Json.fromJson(string);
1✔
2605
    }
2606

2607
    public Object fromJson() {
2608
        return Json.fromJson(getString().get());
1✔
2609
    }
2610

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

2616
    public static Map<String, Object> fromJsonMap(final String string, final int maxDepth) {
2617
        final Object object = Json.fromJson(string, maxDepth);
1✔
2618
        return getStringObjectMap(object);
1✔
2619
    }
2620

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

2633
    public String toXml() {
2634
        return Xml.toXml((Collection) getIterable());
1✔
2635
    }
2636

2637
    public Object fromXml() {
2638
        return Xml.fromXml(getString().get());
1✔
2639
    }
2640

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

2684
    public static String jsonToXml(String json, Xml.XmlStringBuilder.Step identStep) {
2685
        return jsonToXml(json, identStep, null, ROOT);
1✔
2686
    }
2687

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

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

2696
    public static String jsonToXml(String json, String newRootName) {
2697
        return jsonToXml(
1✔
2698
                json,
2699
                Xml.XmlStringBuilder.Step.TWO_SPACES,
2700
                JsonToXmlMode.DEFINE_ROOT_NAME,
2701
                newRootName);
2702
    }
2703

2704
    public static String jsonToXml(String json) {
2705
        return jsonToXml(json, Xml.XmlStringBuilder.Step.TWO_SPACES, null, null);
1✔
2706
    }
2707

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

2718
    public static String jsonToXmlMinimum(String json) {
2719
        return jsonToXmlMinimum(json, Xml.XmlStringBuilder.Step.TWO_SPACES);
1✔
2720
    }
2721

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

2767
    public static String xmlToJson(String xml) {
2768
        return xmlToJson(xml, Json.JsonStringBuilder.Step.TWO_SPACES, null);
1✔
2769
    }
2770

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

2781
    public static String xmlToJsonMinimum(String xml) {
2782
        return xmlToJsonMinimum(xml, Json.JsonStringBuilder.Step.TWO_SPACES);
1✔
2783
    }
2784

2785
    public static String xmlToJson(String xml, Json.JsonStringBuilder.Step identStep) {
2786
        return xmlToJson(xml, identStep, null);
1✔
2787
    }
2788

2789
    public static String xmlToJson(String xml, XmlToJsonMode mode) {
2790
        return xmlToJson(xml, Json.JsonStringBuilder.Step.TWO_SPACES, mode);
1✔
2791
    }
2792

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

2804
    public static void fileXmlToJson(String xmlFileName, String jsonFileName) throws IOException {
2805
        fileXmlToJson(xmlFileName, jsonFileName, Json.JsonStringBuilder.Step.TWO_SPACES);
1✔
2806
    }
1✔
2807

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

2821
    public static void streamXmlToJson(InputStream xmlInputStream, OutputStream jsonOutputStream)
2822
            throws IOException {
2823
        streamXmlToJson(xmlInputStream, jsonOutputStream, Json.JsonStringBuilder.Step.TWO_SPACES);
1✔
2824
    }
1✔
2825

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

2855
    public static void fileJsonToXml(String jsonFileName, String xmlFileName) throws IOException {
2856
        fileJsonToXml(jsonFileName, xmlFileName, Xml.XmlStringBuilder.Step.TWO_SPACES);
1✔
2857
    }
1✔
2858

2859
    public static void jsonFolderToXml(
2860
            String jsonFolder, String xmlFolder, Xml.XmlStringBuilder.Step identStep)
2861
            throws IOException {
2862
        Path sourceRoot = Paths.get(jsonFolder);
1✔
2863
        Path targetRoot = Paths.get(xmlFolder);
1✔
2864
        Files.walkFileTree(
1✔
2865
                sourceRoot,
2866
                new SimpleFileVisitor<>() {
1✔
2867
                    @Override
2868
                    public FileVisitResult visitFile(Path path, BasicFileAttributes attrs)
2869
                            throws IOException {
2870
                        covertJsonToXml(path, sourceRoot, targetRoot, identStep);
1✔
2871
                        return FileVisitResult.CONTINUE;
1✔
2872
                    }
2873
                });
2874
    }
1✔
2875

2876
    public static void jsonFolderToXml(String jsonFolder, String xmlFolder) throws IOException {
2877
        jsonFolderToXml(jsonFolder, xmlFolder, Xml.XmlStringBuilder.Step.TWO_SPACES);
1✔
2878
    }
1✔
2879

2880
    public static void covertJsonToXml(
2881
            Path path, Path sourceRoot, Path targetRoot, Xml.XmlStringBuilder.Step identStep)
2882
            throws IOException {
2883
        Path relativePath = sourceRoot.relativize(path);
1✔
2884
        String fileName = relativePath.getFileName().toString();
1✔
2885
        String xmlFileName;
2886
        if (fileName.endsWith(".json")) {
1✔
2887
            xmlFileName = fileName.substring(0, fileName.length() - 5) + ".xml";
1✔
2888
        } else {
2889
            return;
1✔
2890
        }
2891
        Path targetPath = targetRoot.resolve(relativePath).getParent().resolve(xmlFileName);
1✔
2892
        Files.createDirectories(targetPath.getParent());
1✔
2893
        fileJsonToXml(path.toAbsolutePath().toString(), targetPath.toString(), identStep);
1✔
2894
    }
1✔
2895

2896
    public static void xmlFolderToJson(
2897
            String xmlFolder, String jsonFolder, Json.JsonStringBuilder.Step identStep)
2898
            throws IOException {
2899
        Path sourceRoot = Paths.get(xmlFolder);
1✔
2900
        Path targetRoot = Paths.get(jsonFolder);
1✔
2901
        Files.walkFileTree(
1✔
2902
                sourceRoot,
2903
                new SimpleFileVisitor<>() {
1✔
2904
                    @Override
2905
                    public FileVisitResult visitFile(Path path, BasicFileAttributes attrs)
2906
                            throws IOException {
2907
                        covertXmlToJson(path, sourceRoot, targetRoot, identStep);
1✔
2908
                        return FileVisitResult.CONTINUE;
1✔
2909
                    }
2910
                });
2911
    }
1✔
2912

2913
    public static void xmlFolderToJson(String xmlFolder, String jsonFolder) throws IOException {
2914
        xmlFolderToJson(xmlFolder, jsonFolder, Json.JsonStringBuilder.Step.TWO_SPACES);
1✔
2915
    }
1✔
2916

2917
    public static void covertXmlToJson(
2918
            Path path, Path sourceRoot, Path targetRoot, Json.JsonStringBuilder.Step identStep)
2919
            throws IOException {
2920
        Path relativePath = sourceRoot.relativize(path);
1✔
2921
        String fileName = relativePath.getFileName().toString();
1✔
2922
        String xmlFileName;
2923
        if (fileName.endsWith(".xml")) {
1✔
2924
            xmlFileName = fileName.substring(0, fileName.length() - 4) + ".json";
1✔
2925
        } else {
2926
            return;
1✔
2927
        }
2928
        Path targetPath = targetRoot.resolve(relativePath).getParent().resolve(xmlFileName);
1✔
2929
        Files.createDirectories(targetPath.getParent());
1✔
2930
        fileXmlToJson(path.toAbsolutePath().toString(), targetPath.toString(), identStep);
1✔
2931
    }
1✔
2932

2933
    public static void streamJsonToXml(
2934
            InputStream jsonInputStream,
2935
            OutputStream xmlOutputStream,
2936
            Xml.XmlStringBuilder.Step identStep)
2937
            throws IOException {
2938
        byte[] bytes = jsonInputStream.readAllBytes();
1✔
2939
        String jsonText = new String(removeBom(bytes), detectEncoding(bytes));
1✔
2940
        Object jsonObject = U.fromJson(jsonText);
1✔
2941
        String lineSeparator = System.lineSeparator();
1✔
2942
        String xml;
2943
        if (jsonObject instanceof Map) {
1✔
2944
            xml = formatString(Xml.toXml((Map<?, ?>) jsonObject, identStep), lineSeparator);
1✔
2945
            if (((Map) jsonObject).containsKey(ENCODING)) {
1✔
2946
                String encoding = String.valueOf(((Map) jsonObject).get(ENCODING));
1✔
2947
                xmlOutputStream.write(xml.getBytes(encoding));
1✔
2948
            } else {
1✔
2949
                xmlOutputStream.write(xml.getBytes(StandardCharsets.UTF_8));
1✔
2950
            }
2951
        } else {
2952
            xml = formatString(Xml.toXml((List<?>) jsonObject, identStep), lineSeparator);
1✔
2953
            xmlOutputStream.write(xml.getBytes(StandardCharsets.UTF_8));
1✔
2954
        }
2955
    }
1✔
2956

2957
    public static void streamJsonToXml(InputStream jsonInputStream, OutputStream xmlOutputStream)
2958
            throws IOException {
2959
        streamJsonToXml(jsonInputStream, xmlOutputStream, Xml.XmlStringBuilder.Step.TWO_SPACES);
1✔
2960
    }
1✔
2961

2962
    public static byte[] removeBom(byte[] bytes) {
2963
        if ((bytes.length >= 3) && (bytes[0] == -17) && (bytes[1] == -69) && (bytes[2] == -65)) {
1✔
2964
            return Arrays.copyOfRange(bytes, 3, bytes.length);
1✔
2965
        }
2966
        if ((bytes.length >= 2) && (bytes[0] == -1) && (bytes[1] == -2)) {
1✔
2967
            return Arrays.copyOfRange(bytes, 2, bytes.length);
1✔
2968
        }
2969
        if ((bytes.length >= 2) && (bytes[0] == -2) && (bytes[1] == -1)) {
1✔
2970
            return Arrays.copyOfRange(bytes, 2, bytes.length);
1✔
2971
        }
2972
        return bytes;
1✔
2973
    }
2974

2975
    public static String detectEncoding(byte[] buffer) {
2976
        if (buffer.length < 4) {
1✔
2977
            return "UTF8";
1✔
2978
        }
2979
        String encoding = null;
1✔
2980
        int n =
1✔
2981
                ((buffer[0] & 0xFF) << 24)
2982
                        | ((buffer[1] & 0xFF) << 16)
2983
                        | ((buffer[2] & 0xFF) << 8)
2984
                        | (buffer[3] & 0xFF);
2985
        switch (n) {
1✔
2986
            case 0x0000FEFF:
2987
            case 0x0000003C:
2988
                encoding = "UTF_32BE";
1✔
2989
                break;
1✔
2990
            case 0x003C003F:
2991
                encoding = "UnicodeBigUnmarked";
1✔
2992
                break;
1✔
2993
            case 0xFFFE0000:
2994
            case 0x3C000000:
2995
                encoding = "UTF_32LE";
1✔
2996
                break;
1✔
2997
            // <?
2998
            case 0x3C003F00:
2999
                encoding = "UnicodeLittleUnmarked";
1✔
3000
                break;
1✔
3001
            // <?xm
3002
            case 0x3C3F786D:
3003
                encoding = "UTF8";
1✔
3004
                break;
1✔
3005
            default:
3006
                if ((n >>> 8) == 0xEFBBBF) {
1✔
3007
                    encoding = "UTF8";
1✔
3008
                    break;
1✔
3009
                }
3010
                if ((n >>> 24) == 0x3C) {
1✔
3011
                    break;
1✔
3012
                }
3013
                switch (n >>> 16) {
1✔
3014
                    case 0xFFFE:
3015
                        encoding = "UnicodeLittleUnmarked";
1✔
3016
                        break;
1✔
3017
                    case 0xFEFF:
3018
                        encoding = "UnicodeBigUnmarked";
1✔
3019
                        break;
1✔
3020
                    default:
3021
                        break;
3022
                }
3023
        }
3024
        return encoding == null ? "UTF8" : encoding;
1✔
3025
    }
3026

3027
    public static String formatString(String data, String lineSeparator) {
3028
        if ("\n".equals(lineSeparator)) {
1✔
3029
            return data;
1✔
3030
        }
3031
        return data.replace("\n", lineSeparator);
1✔
3032
    }
3033

3034
    public static String xmlOrJsonToJson(String xmlOrJson, Json.JsonStringBuilder.Step identStep) {
3035
        TextType textType = getTextType(xmlOrJson);
1✔
3036
        final String result;
3037
        if (textType == TextType.JSON) {
1✔
3038
            result = getJsonString(identStep, fromJson(xmlOrJson));
1✔
3039
        } else if (textType == TextType.XML) {
1✔
3040
            result = getJsonString(identStep, fromXml(xmlOrJson));
1✔
3041
        } else {
3042
            result = xmlOrJson;
1✔
3043
        }
3044
        return result;
1✔
3045
    }
3046

3047
    public static String xmlOrJsonToJson(String xmlOrJson) {
3048
        return xmlOrJsonToJson(xmlOrJson, Json.JsonStringBuilder.Step.TWO_SPACES);
1✔
3049
    }
3050

3051
    public static String mergeXmlsOrJsonsToJson(
3052
            List<String> xmlsOrJsons, Json.JsonStringBuilder.Step identStep) {
3053
        Map<String, Object> resultJsonMap = new LinkedHashMap<>();
1✔
3054
        for (String xmlOrJsonToJson : xmlsOrJsons) {
1✔
3055
            TextType textType = getTextType(xmlOrJsonToJson);
1✔
3056
            final Map<String, Object> jsonOrXmlMap;
3057
            if (textType == TextType.JSON) {
1✔
3058
                jsonOrXmlMap = fromJsonMap(xmlOrJsonToJson);
1✔
3059
            } else if (textType == TextType.XML) {
1✔
3060
                jsonOrXmlMap = fromXmlMap(xmlOrJsonToJson);
1✔
3061
            } else {
3062
                continue;
3063
            }
3064
            resultJsonMap = U.update(resultJsonMap, jsonOrXmlMap);
1✔
3065
        }
1✔
3066
        return resultJsonMap.isEmpty() ? "" : Json.toJson(resultJsonMap, identStep);
1✔
3067
    }
3068

3069
    public static String mergeXmlsOrJsonsToJson(List<String> xmlsOrJsons) {
3070
        return mergeXmlsOrJsonsToJson(xmlsOrJsons, Json.JsonStringBuilder.Step.TWO_SPACES);
1✔
3071
    }
3072

3073
    public static String mergeXmlsOrJsonsToXml(
3074
            List<String> xmlsOrJsons, Xml.XmlStringBuilder.Step identStep) {
3075
        Map<String, Object> resultXmlMap = new LinkedHashMap<>();
1✔
3076
        for (String xmlOrJsonToXml : xmlsOrJsons) {
1✔
3077
            TextType textType = getTextType(xmlOrJsonToXml);
1✔
3078
            final Map<String, Object> jsonOrXmlMap;
3079
            if (textType == TextType.JSON) {
1✔
3080
                jsonOrXmlMap = fromJsonMap(xmlOrJsonToXml);
1✔
3081
            } else if (textType == TextType.XML) {
1✔
3082
                jsonOrXmlMap = fromXmlMap(xmlOrJsonToXml);
1✔
3083
            } else {
3084
                continue;
3085
            }
3086
            resultXmlMap = U.update(resultXmlMap, jsonOrXmlMap);
1✔
3087
        }
1✔
3088
        return resultXmlMap.isEmpty() ? "" : Xml.toXml(resultXmlMap, identStep);
1✔
3089
    }
3090

3091
    public static String mergeXmlsOrJsonsToXml(List<String> xmlsOrJsons) {
3092
        return mergeXmlsOrJsonsToXml(xmlsOrJsons, Xml.XmlStringBuilder.Step.TWO_SPACES);
1✔
3093
    }
3094

3095
    @SuppressWarnings("unchecked")
3096
    private static String getJsonString(Json.JsonStringBuilder.Step identStep, Object object) {
3097
        final String result;
3098
        if (object instanceof Map) {
1✔
3099
            result = Json.toJson((Map) object, identStep);
1✔
3100
        } else {
3101
            result = Json.toJson((List) object, identStep);
1✔
3102
        }
3103
        return result;
1✔
3104
    }
3105

3106
    public static String xmlOrJsonToXml(String xmlOrJson, Xml.XmlStringBuilder.Step identStep) {
3107
        TextType textType = getTextType(xmlOrJson);
1✔
3108
        final String result;
3109
        if (textType == TextType.JSON) {
1✔
3110
            result = getXmlString(identStep, fromJson(xmlOrJson));
1✔
3111
        } else if (textType == TextType.XML) {
1✔
3112
            result = getXmlString(identStep, fromXml(xmlOrJson));
1✔
3113
        } else {
3114
            result = xmlOrJson;
1✔
3115
        }
3116
        return result;
1✔
3117
    }
3118

3119
    public static String xmlOrJsonToXml(String xmlOrJson) {
3120
        return xmlOrJsonToXml(xmlOrJson, Xml.XmlStringBuilder.Step.TWO_SPACES);
1✔
3121
    }
3122

3123
    @SuppressWarnings("unchecked")
3124
    private static String getXmlString(Xml.XmlStringBuilder.Step identStep, Object object) {
3125
        final String result;
3126
        if (object instanceof Map) {
1✔
3127
            result = Xml.toXml((Map) object, identStep);
1✔
3128
        } else {
3129
            result = Xml.toXml((List) object, identStep);
1✔
3130
        }
3131
        return result;
1✔
3132
    }
3133

3134
    public enum TextType {
1✔
3135
        JSON,
1✔
3136
        XML,
1✔
3137
        OTHER
1✔
3138
    }
3139

3140
    public static TextType getTextType(String text) {
3141
        String trimmed = trim(text);
1✔
3142
        final TextType textType;
3143
        if (trimmed.startsWith("{") && trimmed.endsWith("}")
1✔
3144
                || trimmed.startsWith("[") && trimmed.endsWith("]")) {
1✔
3145
            textType = TextType.JSON;
1✔
3146
        } else if (trimmed.startsWith("<") && trimmed.endsWith(">")) {
1✔
3147
            textType = TextType.XML;
1✔
3148
        } else {
3149
            textType = TextType.OTHER;
1✔
3150
        }
3151
        return textType;
1✔
3152
    }
3153

3154
    public static String formatJsonOrXml(String jsonOrXml, String identStep) {
3155
        TextType textType = getTextType(jsonOrXml);
1✔
3156
        final String result;
3157
        if (textType == TextType.JSON) {
1✔
3158
            result = formatJson(jsonOrXml, Json.JsonStringBuilder.Step.valueOf(identStep));
1✔
3159
        } else if (textType == TextType.XML) {
1✔
3160
            result = formatXml(jsonOrXml, Xml.XmlStringBuilder.Step.valueOf(identStep));
1✔
3161
        } else {
3162
            result = jsonOrXml;
1✔
3163
        }
3164
        return result;
1✔
3165
    }
3166

3167
    public static String formatJsonOrXml(String jsonOrXml) {
3168
        return formatJsonOrXml(jsonOrXml, "TWO_SPACES");
1✔
3169
    }
3170

3171
    public static String formatJson(String json, Json.JsonStringBuilder.Step identStep) {
3172
        return Json.formatJson(json, identStep);
1✔
3173
    }
3174

3175
    public static String formatJson(String json) {
3176
        return Json.formatJson(json);
1✔
3177
    }
3178

3179
    public static String formatXml(String xml, Xml.XmlStringBuilder.Step identStep) {
3180
        return Xml.formatXml(xml, identStep);
1✔
3181
    }
3182

3183
    public static String formatXml(String xml) {
3184
        return Xml.formatXml(xml);
1✔
3185
    }
3186

3187
    public static String changeXmlEncoding(
3188
            String xml, Xml.XmlStringBuilder.Step identStep, String encoding) {
3189
        return Xml.changeXmlEncoding(xml, identStep, encoding);
1✔
3190
    }
3191

3192
    public static String changeXmlEncoding(String xml, String encoding) {
3193
        return Xml.changeXmlEncoding(xml, encoding);
1✔
3194
    }
3195

3196
    public static Map<String, Object> removeMinusesAndConvertNumbers(Map<String, Object> map) {
3197
        Map<String, Object> outMap = new LinkedHashMap<>();
1✔
3198
        for (Map.Entry<String, Object> entry : map.entrySet()) {
1✔
3199
            final String newKey;
3200
            if (entry.getKey().startsWith("-")) {
1✔
3201
                newKey = entry.getKey().substring(1);
1✔
3202
            } else {
3203
                newKey = entry.getKey();
1✔
3204
            }
3205
            if (!entry.getKey().equals(SELF_CLOSING) && !entry.getKey().equals(OMIT_XML_DECL)) {
1✔
3206
                outMap.put(newKey, makeObject(entry.getValue()));
1✔
3207
            }
3208
        }
1✔
3209
        return outMap;
1✔
3210
    }
3211

3212
    @SuppressWarnings("unchecked")
3213
    private static Object makeObject(Object value) {
3214
        final Object result;
3215
        if (value instanceof List) {
1✔
3216
            List<Object> values = new ArrayList<>();
1✔
3217
            for (Object item : (List) value) {
1✔
3218
                values.add(
1✔
3219
                        item instanceof Map
1✔
3220
                                ? removeMinusesAndConvertNumbers((Map<String, Object>) item)
1✔
3221
                                : item);
1✔
3222
            }
1✔
3223
            result = values;
1✔
3224
        } else if (value instanceof Map) {
1✔
3225
            result = removeMinusesAndConvertNumbers((Map) value);
1✔
3226
        } else {
3227
            String stringValue = String.valueOf(value);
1✔
3228
            result = isJsonNumber(stringValue) ? Xml.stringToNumber(stringValue) : value;
1✔
3229
        }
3230
        return result;
1✔
3231
    }
3232

3233
    public static boolean isJsonNumber(final String string) {
3234
        boolean eFound = false;
1✔
3235
        boolean periodValid = true;
1✔
3236
        boolean pmValid = true;
1✔
3237
        boolean numberEncountered = false;
1✔
3238
        for (char ch : string.toCharArray()) {
1✔
3239
            if (pmValid) {
1✔
3240
                pmValid = false;
1✔
3241
                if (ch == '-') {
1✔
3242
                    continue;
1✔
3243
                }
3244
            }
3245
            if (!eFound && (ch == 'e' || ch == 'E')) {
1✔
3246
                eFound = true;
1✔
3247
                periodValid = false;
1✔
3248
                pmValid = true;
1✔
3249
                numberEncountered = false;
1✔
3250
                continue;
1✔
3251
            }
3252
            if (periodValid && ch == '.') {
1✔
3253
                periodValid = false;
1✔
3254
                continue;
1✔
3255
            }
3256
            if (ch < '0' || ch > '9') {
1✔
3257
                return false;
1✔
3258
            }
3259
            numberEncountered = true;
1✔
3260
        }
3261
        return numberEncountered;
1✔
3262
    }
3263

3264
    @SuppressWarnings("unchecked")
3265
    public static Map<String, Object> replaceSelfClosingWithNull(Map<String, Object> map) {
3266
        return (Map<String, Object>) replaceSelfClosingWithValue(map, null);
1✔
3267
    }
3268

3269
    @SuppressWarnings("unchecked")
3270
    public static Map<String, Object> replaceSelfClosingWithEmpty(Map<String, Object> map) {
3271
        Object result = replaceSelfClosingWithValue(map, "");
1✔
3272
        if (result instanceof Map) {
1✔
3273
            return (Map<String, Object>) result;
1✔
3274
        }
3275
        return Collections.emptyMap();
1✔
3276
    }
3277

3278
    @SuppressWarnings("unchecked")
3279
    public static Object replaceSelfClosingWithValue(Map<String, Object> map, String value) {
3280
        Object outMap = new LinkedHashMap<>();
1✔
3281
        for (Map.Entry<String, Object> entry : map.entrySet()) {
1✔
3282
            if (SELF_CLOSING.equals(entry.getKey()) && "true".equals(entry.getValue())) {
1✔
3283
                if (map.size() == 1) {
1✔
3284
                    outMap = value;
1✔
3285
                    break;
1✔
3286
                }
3287
            } else {
3288
                ((Map<String, Object>) outMap)
1✔
3289
                        .put(
1✔
3290
                                String.valueOf(entry.getKey()),
1✔
3291
                                makeObjectSelfClose(entry.getValue(), value));
1✔
3292
            }
3293
        }
1✔
3294
        return outMap;
1✔
3295
    }
3296

3297
    @SuppressWarnings("unchecked")
3298
    private static Object makeObjectSelfClose(Object value, String newValue) {
3299
        final Object result;
3300
        if (value instanceof List) {
1✔
3301
            List<Object> values = new ArrayList<>();
1✔
3302
            for (Object item : (List) value) {
1✔
3303
                values.add(
1✔
3304
                        item instanceof Map
1✔
3305
                                ? replaceSelfClosingWithValue((Map) item, newValue)
1✔
3306
                                : item);
1✔
3307
            }
1✔
3308
            result = values;
1✔
3309
        } else if (value instanceof Map) {
1✔
3310
            result = replaceSelfClosingWithValue((Map) value, newValue);
1✔
3311
        } else {
3312
            result = value;
1✔
3313
        }
3314
        return result;
1✔
3315
    }
3316

3317
    public static Map<String, Object> replaceMinusWithAt(Map<String, Object> map) {
3318
        if (map == null) {
1✔
3319
            return null;
1✔
3320
        }
3321
        Map<String, Object> outMap = new LinkedHashMap<>();
1✔
3322
        for (Map.Entry<String, Object> entry : map.entrySet()) {
1✔
3323
            outMap.put(
1✔
3324
                    String.valueOf(entry.getKey()).startsWith("-")
1✔
3325
                            ? "@" + String.valueOf(entry.getKey()).substring(1)
1✔
3326
                            : String.valueOf(entry.getKey()),
1✔
3327
                    replaceMinusWithAtValue(entry.getValue()));
1✔
3328
        }
1✔
3329
        return outMap;
1✔
3330
    }
3331

3332
    @SuppressWarnings("unchecked")
3333
    private static Object replaceMinusWithAtValue(Object value) {
3334
        final Object result;
3335
        if (value instanceof List) {
1✔
3336
            List<Object> values = new ArrayList<>();
1✔
3337
            for (Object item : (List) value) {
1✔
3338
                values.add(item instanceof Map ? replaceMinusWithAt((Map) item) : item);
1✔
3339
            }
1✔
3340
            result = values;
1✔
3341
        } else if (value instanceof Map) {
1✔
3342
            result = replaceMinusWithAt((Map) value);
1✔
3343
        } else {
3344
            result = value;
1✔
3345
        }
3346
        return result;
1✔
3347
    }
3348

3349
    public static Map<String, Object> replaceEmptyValueWithNull(Map<String, Object> map) {
3350
        if (map == null || map.isEmpty()) {
1✔
3351
            return null;
1✔
3352
        }
3353
        Map<String, Object> outMap = new LinkedHashMap<>();
1✔
3354
        for (Map.Entry<String, Object> entry : map.entrySet()) {
1✔
3355
            outMap.put(String.valueOf(entry.getKey()), makeObjectEmptyValue(entry.getValue()));
1✔
3356
        }
1✔
3357
        return outMap;
1✔
3358
    }
3359

3360
    @SuppressWarnings("unchecked")
3361
    private static Object makeObjectEmptyValue(Object value) {
3362
        final Object result;
3363
        if (value instanceof List) {
1✔
3364
            List<Object> values = new ArrayList<>();
1✔
3365
            for (Object item : (List) value) {
1✔
3366
                values.add(item instanceof Map ? replaceEmptyValueWithNull((Map) item) : item);
1✔
3367
            }
1✔
3368
            result = values;
1✔
3369
        } else if (value instanceof Map) {
1✔
3370
            result = replaceEmptyValueWithNull((Map) value);
1✔
3371
        } else {
3372
            result = value;
1✔
3373
        }
3374
        return result;
1✔
3375
    }
3376

3377
    public static Object replaceEmptyValueWithEmptyString(Map<String, Object> map) {
3378
        if (map.isEmpty()) {
1✔
3379
            return "";
1✔
3380
        }
3381
        Map<String, Object> outMap = new LinkedHashMap<>();
1✔
3382
        for (Map.Entry<String, Object> entry : map.entrySet()) {
1✔
3383
            outMap.put(String.valueOf(entry.getKey()), makeObjectEmptyString(entry.getValue()));
1✔
3384
        }
1✔
3385
        return outMap;
1✔
3386
    }
3387

3388
    @SuppressWarnings("unchecked")
3389
    private static Object makeObjectEmptyString(Object value) {
3390
        final Object result;
3391
        if (value instanceof List) {
1✔
3392
            List<Object> values = new ArrayList<>();
1✔
3393
            for (Object item : (List) value) {
1✔
3394
                values.add(
1✔
3395
                        item instanceof Map ? replaceEmptyValueWithEmptyString((Map) item) : item);
1✔
3396
            }
1✔
3397
            result = values;
1✔
3398
        } else if (value instanceof Map) {
1✔
3399
            result = replaceEmptyValueWithEmptyString((Map) value);
1✔
3400
        } else {
3401
            result = value;
1✔
3402
        }
3403
        return result;
1✔
3404
    }
3405

3406
    public static Map<String, Object> forceAttributeUsage(Map<String, Object> map) {
3407
        Map<String, Object> outMap = new LinkedHashMap<>();
1✔
3408
        for (Map.Entry<String, Object> entry : map.entrySet()) {
1✔
3409
            outMap.put(
1✔
3410
                    entry.getValue() instanceof Map
1✔
3411
                                    || entry.getValue() instanceof List
1✔
3412
                                    || String.valueOf(entry.getKey()).startsWith("-")
1✔
3413
                            ? String.valueOf(entry.getKey())
1✔
3414
                            : "-" + entry.getKey(),
1✔
3415
                    makeAttributeUsage(entry.getValue()));
1✔
3416
        }
1✔
3417
        return outMap;
1✔
3418
    }
3419

3420
    @SuppressWarnings("unchecked")
3421
    private static Object makeAttributeUsage(Object value) {
3422
        final Object result;
3423
        if (value instanceof List) {
1✔
3424
            List<Object> values = new ArrayList<>();
1✔
3425
            for (Object item : (List) value) {
1✔
3426
                values.add(item instanceof Map ? forceAttributeUsage((Map) item) : item);
1✔
3427
            }
1✔
3428
            result = values;
1✔
3429
        } else if (value instanceof Map) {
1✔
3430
            result = forceAttributeUsage((Map) value);
1✔
3431
        } else {
3432
            result = value;
1✔
3433
        }
3434
        return result;
1✔
3435
    }
3436

3437
    public static Map<String, Object> replaceNullWithEmptyValue(Map<String, Object> map) {
3438
        Map<String, Object> outMap = new LinkedHashMap<>();
1✔
3439
        for (Map.Entry<String, Object> entry : map.entrySet()) {
1✔
3440
            outMap.put(
1✔
3441
                    entry.getKey(),
1✔
3442
                    entry.getValue() == null
1✔
3443
                            ? new LinkedHashMap<>()
1✔
3444
                            : makeReplaceNullValue(entry.getValue()));
1✔
3445
        }
1✔
3446
        return outMap;
1✔
3447
    }
3448

3449
    @SuppressWarnings("unchecked")
3450
    private static Object makeReplaceNullValue(Object value) {
3451
        final Object result;
3452
        if (value instanceof List) {
1✔
3453
            List<Object> values = new ArrayList<>();
1✔
3454
            for (Object item : (List) value) {
1✔
3455
                values.add(item instanceof Map ? replaceNullWithEmptyValue((Map) item) : item);
1✔
3456
            }
1✔
3457
            result = values;
1✔
3458
        } else if (value instanceof Map) {
1✔
3459
            result = replaceNullWithEmptyValue((Map) value);
1✔
3460
        } else {
3461
            result = value;
1✔
3462
        }
3463
        return result;
1✔
3464
    }
3465

3466
    public static Map<String, Object> replaceEmptyStringWithEmptyValue(Map<String, Object> map) {
3467
        Map<String, Object> outMap = new LinkedHashMap<>();
1✔
3468
        for (Map.Entry<String, Object> entry : map.entrySet()) {
1✔
3469
            outMap.put(
1✔
3470
                    entry.getKey(),
1✔
3471
                    "".equals(entry.getValue())
1✔
3472
                            ? new LinkedHashMap<>()
1✔
3473
                            : makeReplaceEmptyString(entry.getValue()));
1✔
3474
        }
1✔
3475
        return outMap;
1✔
3476
    }
3477

3478
    @SuppressWarnings("unchecked")
3479
    private static Object makeReplaceEmptyString(Object value) {
3480
        final Object result;
3481
        if (value instanceof List) {
1✔
3482
            List<Object> values = new ArrayList<>();
1✔
3483
            for (Object item : (List) value) {
1✔
3484
                values.add(
1✔
3485
                        item instanceof Map ? replaceEmptyStringWithEmptyValue((Map) item) : item);
1✔
3486
            }
1✔
3487
            result = values;
1✔
3488
        } else if (value instanceof Map) {
1✔
3489
            result = replaceEmptyStringWithEmptyValue((Map) value);
1✔
3490
        } else {
3491
            result = value;
1✔
3492
        }
3493
        return result;
1✔
3494
    }
3495

3496
    public static Map<String, Object> replaceNumberAndBooleanWithString(Map<String, Object> map) {
3497
        Map<String, Object> outMap = new LinkedHashMap<>();
1✔
3498
        for (Map.Entry<String, Object> entry : map.entrySet()) {
1✔
3499
            outMap.put(
1✔
3500
                    entry.getKey(),
1✔
3501
                    entry.getValue() instanceof Boolean || entry.getValue() instanceof Number
1✔
3502
                            ? String.valueOf(entry.getValue())
1✔
3503
                            : makeReplaceNumberAndBoolean(entry.getValue()));
1✔
3504
        }
1✔
3505
        return outMap;
1✔
3506
    }
3507

3508
    @SuppressWarnings("unchecked")
3509
    private static Object makeReplaceNumberAndBoolean(Object value) {
3510
        final Object result;
3511
        if (value instanceof List) {
1✔
3512
            List<Object> values = new ArrayList<>();
1✔
3513
            for (Object item : (List) value) {
1✔
3514
                if (item instanceof Map) {
1✔
3515
                    values.add(replaceNumberAndBooleanWithString((Map) item));
1✔
3516
                } else if (item instanceof Number || item instanceof Boolean || isNull(item)) {
1✔
3517
                    values.add(String.valueOf(item));
1✔
3518
                } else {
3519
                    values.add(item);
1✔
3520
                }
3521
            }
1✔
3522
            result = values;
1✔
3523
        } else if (value instanceof Map) {
1✔
3524
            result = replaceNumberAndBooleanWithString((Map) value);
1✔
3525
        } else if (isNull(value)) {
1✔
3526
            result = "null";
1✔
3527
        } else {
3528
            result = value;
1✔
3529
        }
3530
        return result;
1✔
3531
    }
3532

3533
    public static Map<String, Object> replaceFirstLevel(Map<String, Object> map) {
3534
        return replaceFirstLevel(map, 0);
1✔
3535
    }
3536

3537
    @SuppressWarnings("unchecked")
3538
    public static Map<String, Object> replaceFirstLevel(Map<String, Object> map, int level) {
3539
        Map<String, Object> outMap = new LinkedHashMap<>();
1✔
3540
        for (Map.Entry<String, Object> entry : map.entrySet()) {
1✔
3541
            outMap.put(entry.getKey(), makeReplaceFirstLevel(entry.getValue(), level + 1));
1✔
3542
        }
1✔
3543
        if (level == 0 && Xml.XmlValue.getMapValue(outMap) instanceof Map) {
1✔
3544
            Map<String, Object> outMap2 = (Map<String, Object>) Xml.XmlValue.getMapValue(outMap);
1✔
3545
            if (SELF_CLOSING.equals(Xml.XmlValue.getMapKey(outMap2))
1✔
3546
                    && "true".equals(Xml.XmlValue.getMapValue(outMap2))) {
1✔
3547
                outMap2.remove(SELF_CLOSING);
1✔
3548
            }
3549
            return outMap2;
1✔
3550
        }
3551
        return outMap;
1✔
3552
    }
3553

3554
    @SuppressWarnings("unchecked")
3555
    private static Object makeReplaceFirstLevel(Object value, int level) {
3556
        final Object result;
3557
        if (value instanceof List) {
1✔
3558
            List<Object> values = new ArrayList<>();
1✔
3559
            for (Object item : (List) value) {
1✔
3560
                values.add(item instanceof Map ? replaceFirstLevel((Map) item, level + 1) : item);
1✔
3561
            }
1✔
3562
            result = values;
1✔
3563
        } else if (value instanceof Map) {
1✔
3564
            result = replaceFirstLevel((Map) value, level + 1);
1✔
3565
        } else {
3566
            result = value;
1✔
3567
        }
3568
        return result;
1✔
3569
    }
3570

3571
    public static Map<String, Object> replaceNilWithNull(Map<String, Object> map) {
3572
        Map<String, Object> outMap = new LinkedHashMap<>();
1✔
3573
        for (Map.Entry<String, Object> entry : map.entrySet()) {
1✔
3574
            Object outValue = makeReplaceNilWithNull(entry.getValue());
1✔
3575
            if (outValue instanceof Map
1✔
3576
                    && (NIL_KEY.equals(Xml.XmlValue.getMapKey(outValue))
1✔
3577
                            || Xml.XmlValue.getMapKey(outValue).endsWith(":nil"))
1✔
3578
                    && "true".equals(Xml.XmlValue.getMapValue(outValue))
1✔
3579
                    && ((Map) outValue).containsKey(SELF_CLOSING)
1✔
3580
                    && "true".equals(((Map) outValue).get(SELF_CLOSING))) {
1✔
3581
                outValue = null;
1✔
3582
            }
3583
            outMap.put(entry.getKey(), outValue);
1✔
3584
        }
1✔
3585
        return outMap;
1✔
3586
    }
3587

3588
    @SuppressWarnings("unchecked")
3589
    private static Object makeReplaceNilWithNull(Object value) {
3590
        final Object result;
3591
        if (value instanceof List) {
1✔
3592
            List<Object> values = new ArrayList<>();
1✔
3593
            for (Object item : (List) value) {
1✔
3594
                values.add(item instanceof Map ? replaceNilWithNull((Map) item) : item);
1✔
3595
            }
1✔
3596
            result = values;
1✔
3597
        } else if (value instanceof Map) {
1✔
3598
            result = replaceNilWithNull((Map) value);
1✔
3599
        } else {
3600
            result = value;
1✔
3601
        }
3602
        return result;
1✔
3603
    }
3604

3605
    public static Map<String, Object> deepCopyMap(Map<String, Object> map) {
3606
        Map<String, Object> outMap = new LinkedHashMap<>();
1✔
3607
        for (Map.Entry<String, Object> entry : map.entrySet()) {
1✔
3608
            outMap.put(entry.getKey(), makeDeepCopyMap(entry.getValue()));
1✔
3609
        }
1✔
3610
        return outMap;
1✔
3611
    }
3612

3613
    @SuppressWarnings("unchecked")
3614
    private static Object makeDeepCopyMap(Object value) {
3615
        final Object result;
3616
        if (value instanceof List) {
1✔
3617
            List<Object> values = new ArrayList<>();
1✔
3618
            for (Object item : (List) value) {
1✔
3619
                values.add(item instanceof Map ? deepCopyMap((Map) item) : item);
1✔
3620
            }
1✔
3621
            result = values;
1✔
3622
        } else if (value instanceof Map) {
1✔
3623
            result = deepCopyMap((Map) value);
1✔
3624
        } else {
3625
            result = value;
1✔
3626
        }
3627
        return result;
1✔
3628
    }
3629

3630
    public static Builder objectBuilder() {
3631
        return new U.Builder();
1✔
3632
    }
3633

3634
    public static class Builder {
3635
        private final Map<String, Object> data;
3636

3637
        public Builder() {
1✔
3638
            data = new LinkedHashMap<>();
1✔
3639
        }
1✔
3640

3641
        public Builder add(final String key, final Object value) {
3642
            data.put(key, value);
1✔
3643
            return this;
1✔
3644
        }
3645

3646
        public Builder add(final Object value) {
3647
            data.put(String.valueOf(data.size()), value);
1✔
3648
            return this;
1✔
3649
        }
3650

3651
        public <T> T get(final String path) {
3652
            return U.get(data, path);
1✔
3653
        }
3654

3655
        public <T> T get(final List<String> paths) {
3656
            return U.get(data, paths);
1✔
3657
        }
3658

3659
        public Builder set(final String path, final Object value) {
3660
            U.set(data, path, value);
1✔
3661
            return this;
1✔
3662
        }
3663

3664
        public Builder set(final List<String> paths, final Object value) {
3665
            U.set(data, paths, value);
1✔
3666
            return this;
1✔
3667
        }
3668

3669
        public Builder remove(final String key) {
3670
            U.remove(data, key);
1✔
3671
            return this;
1✔
3672
        }
3673

3674
        public Builder remove(final List<String> keys) {
3675
            U.remove(data, keys);
1✔
3676
            return this;
1✔
3677
        }
3678

3679
        public Builder clear() {
3680
            data.clear();
1✔
3681
            return this;
1✔
3682
        }
3683

3684
        public boolean isEmpty() {
3685
            return data.isEmpty();
1✔
3686
        }
3687

3688
        public int size() {
3689
            return data.size();
1✔
3690
        }
3691

3692
        public Builder add(final Builder builder) {
3693
            data.put(String.valueOf(data.size()), builder.build());
1✔
3694
            return this;
1✔
3695
        }
3696

3697
        public Builder add(final String key, final ArrayBuilder builder) {
3698
            data.put(key, builder.build());
1✔
3699
            return this;
1✔
3700
        }
3701

3702
        public Builder add(final String key, final Builder builder) {
3703
            data.put(key, builder.build());
1✔
3704
            return this;
1✔
3705
        }
3706

3707
        public Builder add(final Map<String, Object> map) {
3708
            data.putAll(deepCopyMap(map));
1✔
3709
            return this;
1✔
3710
        }
3711

3712
        public Builder update(final Map<String, Object> map) {
3713
            U.update(data, deepCopyMap(map));
1✔
3714
            return this;
1✔
3715
        }
3716

3717
        public Builder addNull(final String key) {
3718
            data.put(key, null);
1✔
3719
            return this;
1✔
3720
        }
3721

3722
        @SuppressWarnings("unchecked")
3723
        public Map<String, Object> build() {
3724
            return (Map<String, Object>) ((LinkedHashMap<?, ?>) data).clone();
1✔
3725
        }
3726

3727
        public String toXml() {
3728
            return Xml.toXml(data);
1✔
3729
        }
3730

3731
        public static Builder fromXml(final String xml) {
3732
            final Builder builder = new Builder();
1✔
3733
            builder.data.putAll(fromXmlMap(xml));
1✔
3734
            return builder;
1✔
3735
        }
3736

3737
        public static Builder fromMap(final Map<String, Object> map) {
3738
            final Builder builder = new Builder();
1✔
3739
            builder.data.putAll(deepCopyMap(map));
1✔
3740
            return builder;
1✔
3741
        }
3742

3743
        public String toJson() {
3744
            return Json.toJson(data);
1✔
3745
        }
3746

3747
        public static Builder fromJson(final String json) {
3748
            final Builder builder = new Builder();
1✔
3749
            builder.data.putAll(fromJsonMap(json));
1✔
3750
            return builder;
1✔
3751
        }
3752

3753
        public Chain<Object> toChain() {
3754
            return new U.Chain<>(data.entrySet());
1✔
3755
        }
3756

3757
        @Override
3758
        public String toString() {
3759
            return data.toString();
1✔
3760
        }
3761
    }
3762

3763
    public static ArrayBuilder arrayBuilder() {
3764
        return new U.ArrayBuilder();
1✔
3765
    }
3766

3767
    public static class ArrayBuilder {
3768
        private final List<Object> data;
3769

3770
        public ArrayBuilder() {
1✔
3771
            data = new ArrayList<>();
1✔
3772
        }
1✔
3773

3774
        public ArrayBuilder add(final Object value) {
3775
            data.add(value);
1✔
3776
            return this;
1✔
3777
        }
3778

3779
        public ArrayBuilder addNull() {
3780
            data.add(null);
1✔
3781
            return this;
1✔
3782
        }
3783

3784
        public <T> T get(final String path) {
3785
            return U.get(U.getStringObjectMap(data), "value." + path);
1✔
3786
        }
3787

3788
        public <T> T get(final List<String> paths) {
3789
            List<String> newPaths = new ArrayList<>();
1✔
3790
            newPaths.add("value");
1✔
3791
            newPaths.addAll(paths);
1✔
3792
            return U.get(U.getStringObjectMap(data), newPaths);
1✔
3793
        }
3794

3795
        public ArrayBuilder set(final int index, final Object value) {
3796
            data.set(index, value);
1✔
3797
            return this;
1✔
3798
        }
3799

3800
        public ArrayBuilder remove(final int index) {
3801
            data.remove(index);
1✔
3802
            return this;
1✔
3803
        }
3804

3805
        public ArrayBuilder clear() {
3806
            data.clear();
1✔
3807
            return this;
1✔
3808
        }
3809

3810
        public boolean isEmpty() {
3811
            return data.isEmpty();
1✔
3812
        }
3813

3814
        public int size() {
3815
            return data.size();
1✔
3816
        }
3817

3818
        public ArrayBuilder add(final ArrayBuilder builder) {
3819
            data.addAll(builder.build());
1✔
3820
            return this;
1✔
3821
        }
3822

3823
        public ArrayBuilder add(final Builder builder) {
3824
            data.add(builder.build());
1✔
3825
            return this;
1✔
3826
        }
3827

3828
        @SuppressWarnings("unchecked")
3829
        public ArrayBuilder merge(final List<Object> list) {
3830
            U.merge(data, (List<Object>) ((ArrayList<?>) list).clone());
1✔
3831
            return this;
1✔
3832
        }
3833

3834
        @SuppressWarnings("unchecked")
3835
        public List<Object> build() {
3836
            return (List<Object>) ((ArrayList<?>) data).clone();
1✔
3837
        }
3838

3839
        public String toXml() {
3840
            return Xml.toXml(data);
1✔
3841
        }
3842

3843
        public static ArrayBuilder fromXml(final String xml) {
3844
            final ArrayBuilder builder = new ArrayBuilder();
1✔
3845
            builder.data.addAll(U.<List<Object>>fromXml(xml));
1✔
3846
            return builder;
1✔
3847
        }
3848

3849
        public String toJson() {
3850
            return Json.toJson(data);
1✔
3851
        }
3852

3853
        public static ArrayBuilder fromJson(final String json) {
3854
            final ArrayBuilder builder = new ArrayBuilder();
1✔
3855
            builder.data.addAll(U.<List<Object>>fromJson(json));
1✔
3856
            return builder;
1✔
3857
        }
3858

3859
        public Chain<Object> toChain() {
3860
            return new U.Chain<>(data);
1✔
3861
        }
3862

3863
        @Override
3864
        public String toString() {
3865
            return data.toString();
1✔
3866
        }
3867
    }
3868

3869
    public static Map<String, Object> propertiesToMap(Properties properties) {
3870
        Map<String, Object> map = new LinkedHashMap<>();
1✔
3871
        if (properties != null && !properties.isEmpty()) {
1✔
3872
            Enumeration<?> enumProperties = properties.propertyNames();
1✔
3873
            while (enumProperties.hasMoreElements()) {
1✔
3874
                String name = (String) enumProperties.nextElement();
1✔
3875
                map.put(name, properties.getProperty(name));
1✔
3876
            }
1✔
3877
        }
3878
        return map;
1✔
3879
    }
3880

3881
    public static Properties mapToProperties(Map<String, Object> map) {
3882
        Properties properties = new Properties();
1✔
3883
        if (map != null) {
1✔
3884
            for (final Map.Entry<String, Object> entry : map.entrySet()) {
1✔
3885
                if (!isNull(entry.getValue())) {
1✔
3886
                    properties.put(entry.getKey(), String.valueOf(entry.getValue()));
1✔
3887
                }
3888
            }
1✔
3889
        }
3890
        return properties;
1✔
3891
    }
3892
}
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

© 2026 Coveralls, Inc