All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.underscore.lodash.U Maven / Gradle / Ivy

The newest version!
/*
 * The MIT License (MIT)
 *
 * Copyright 2015-2020 Valentyn Kolesnikov
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package com.github.underscore.lodash;

import com.github.underscore.Function3;
import com.github.underscore.PredicateIndexed;
import com.github.underscore.Tuple;
import com.github.underscore.Optional;
import java.util.*;
import java.util.function.BinaryOperator;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;

public class U extends com.github.underscore.U {
    private static final int DEFAULT_TRUNC_LENGTH = 30;
    private static final String DEFAULT_TRUNC_OMISSION = "...";
    private static final java.util.regex.Pattern RE_LATIN_1 = java.util.regex.Pattern.compile(
        "[\\xc0-\\xd6\\xd8-\\xde\\xdf-\\xf6\\xf8-\\xff]");
    private static final java.util.regex.Pattern RE_PROP_NAME = java.util.regex.Pattern.compile(
        "[^.\\[\\]]+|\\[(?:(-?\\d+(?:\\.\\d+)?)|([\"'])((?:(?!\2)\\[^\\]|\\.)*?)\2)\\]|(?=(\\.|\\[\\])(?:\4|$))");
    private static final Map DEBURRED_LETTERS = new LinkedHashMap();
    private static final Map> DEFAULT_HEADER_FIELDS = new HashMap>();
    private static final Set SUPPORTED_HTTP_METHODS = new HashSet(
        Arrays.asList("GET", "POST", "PUT", "DELETE"));
    private static final int BUFFER_LENGTH_1024 = 1024;
    private static final int RESPONSE_CODE_400 = 400;
    private static String upper = "[A-Z\\xc0-\\xd6\\xd8-\\xde\\u0400-\\u04FF]";
    private static String lower = "[a-z\\xdf-\\xf6\\xf8-\\xff]+";
    private static java.util.regex.Pattern reWords = java.util.regex.Pattern.compile(
        upper + "+(?=" + upper + lower + ")|" + upper + "?" + lower + "|" + upper + "+|[0-9]+");

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

    public enum Mode {
        REPLACE_SELF_CLOSING_WITH_NULL,
        REPLACE_SELF_CLOSING_WITH_EMPTY;
    }

    public U(final Iterable iterable) {
        super(iterable);
    }

    public U(final String string) {
        super(string);
    }

    public static class Chain extends com.github.underscore.U.Chain {
        public Chain(final T item) {
            super(item);
        }
        public Chain(final List list) {
            super(list);
        }

        public Chain first() {
            return new Chain(U.first(value()));
        }

        public Chain first(int n) {
            return new Chain(U.first(value(), n));
        }

        public Chain firstOrNull() {
            return new Chain(U.firstOrNull(value()));
        }

        public Chain firstOrNull(final Predicate pred) {
            return new Chain(U.firstOrNull(value(), pred));
        }

        public Chain initial() {
            return new Chain(U.initial(value()));
        }

        public Chain initial(int n) {
            return new Chain(U.initial(value(), n));
        }

        public Chain last() {
            return new Chain(U.last(value()));
        }

        public Chain last(int n) {
            return new Chain(U.last(value(), n));
        }

        public Chain lastOrNull() {
            return new Chain(U.lastOrNull(value()));
        }

        public Chain lastOrNull(final Predicate pred) {
            return new Chain(U.lastOrNull(value(), pred));
        }

        public Chain rest() {
            return new Chain(U.rest(value()));
        }

        public Chain rest(int n) {
            return new Chain(U.rest(value(), n));
        }

        public Chain compact() {
            return new Chain(U.compact(value()));
        }

        public Chain compact(final T falsyValue) {
            return new Chain(U.compact(value(), falsyValue));
        }

        @SuppressWarnings("unchecked")
        public Chain flatten() {
            return new Chain(U.flatten(value()));
        }

        public  Chain map(final Function func) {
            return new Chain(U.map(value(), func));
        }

        public  Chain mapIndexed(final BiFunction func) {
            return new Chain(U.mapIndexed(value(), func));
        }

        public Chain filter(final Predicate pred) {
            return new Chain(U.filter(value(), pred));
        }

        public Chain filterIndexed(final PredicateIndexed pred) {
            return new Chain(U.filterIndexed(value(), pred));
        }

        public Chain rejectIndexed(final PredicateIndexed pred) {
            return new Chain(U.rejectIndexed(value(), pred));
        }

        public Chain reject(final Predicate pred) {
            return new Chain(U.reject(value(), pred));
        }

        public Chain filterFalse(final Predicate pred) {
            return new Chain(U.filterFalse(value(), pred));
        }

        public  Chain reduce(final BiFunction func, final F zeroElem) {
            return new Chain(U.reduce(value(), func, zeroElem));
        }

        public Chain> reduce(final BinaryOperator func) {
            return new Chain>(U.reduce(value(), func));
        }

        public  Chain reduceRight(final BiFunction func, final F zeroElem) {
            return new Chain(U.reduceRight(value(), func, zeroElem));
        }

        public Chain> reduceRight(final BinaryOperator func) {
            return new Chain>(U.reduceRight(value(), func));
        }

        public Chain> find(final Predicate pred) {
            return new Chain>(U.find(value(), pred));
        }

        public Chain> findLast(final Predicate pred) {
            return new Chain>(U.findLast(value(), pred));
        }

        @SuppressWarnings("unchecked")
        public Chain max() {
            return new Chain(U.max((Collection) value()));
        }

        public > Chain max(final Function func) {
            return new Chain(U.max(value(), func));
        }

        @SuppressWarnings("unchecked")
        public Chain min() {
            return new Chain(U.min((Collection) value()));
        }

        public > Chain min(final Function func) {
            return new Chain(U.min(value(), func));
        }

        @SuppressWarnings("unchecked")
        public Chain sort() {
            return new Chain(U.sort((List) value()));
        }

        @SuppressWarnings("unchecked")
        public > Chain sortWith(final Comparator comparator) {
            return new Chain(U.sortWith((List) value(), comparator));
        }

        public > Chain sortBy(final Function func) {
            return new Chain(U.sortBy(value(), func));
        }

        @SuppressWarnings("unchecked")
        public  Chain> sortBy(final K key) {
            return new Chain>(U.sortBy((List>) value(), key));
        }

        public  Chain>> groupBy(final Function func) {
            return new Chain>>(U.groupBy(value(), func));
        }

        public  Chain>> groupBy(final Function func,
            final BinaryOperator binaryOperator) {
            return new Chain>>(U.groupBy(value(), func, binaryOperator));
        }

        public Chain>> indexBy(final String property) {
            return new Chain>>(U.indexBy(value(), property));
        }

        public  Chain> countBy(final Function func) {
            return new Chain>(U.countBy(value(), func));
        }

        public Chain> countBy() {
            return new Chain>(U.countBy(value()));
        }

        public Chain shuffle() {
            return new Chain(U.shuffle(value()));
        }

        public Chain sample() {
            return new Chain(U.sample(value()));
        }

        public Chain sample(final int howMany) {
            return new Chain(U.newArrayList(U.sample(value(), howMany)));
        }

        public Chain tap(final Consumer func) {
            U.tap(value(), func);
            return new Chain(value());
        }

        public Chain forEach(final Consumer func) {
            U.forEach(value(), func);
            return new Chain(value());
        }

        public Chain forEachRight(final Consumer func) {
            U.forEachRight(value(), func);
            return new Chain(value());
        }

        public Chain every(final Predicate pred) {
            return new Chain(U.every(value(), pred));
        }

        public Chain some(final Predicate pred) {
            return new Chain(U.some(value(), pred));
        }

        public Chain count(final Predicate pred) {
            return new Chain(U.count(value(), pred));
        }

        public Chain contains(final T elem) {
            return new Chain(U.contains(value(), elem));
        }

        public Chain containsWith(final T elem) {
            return new Chain(U.containsWith(value(), elem));
        }

        public Chain invoke(final String methodName, final List args) {
            return new Chain(U.invoke(value(), methodName, args));
        }

        public Chain invoke(final String methodName) {
            return new Chain(U.invoke(value(), methodName));
        }

        public Chain pluck(final String propertyName) {
            return new Chain(U.pluck(value(), propertyName));
        }

        public  Chain where(final List> properties) {
            return new Chain(U.where(value(), properties));
        }

        public  Chain> findWhere(final List> properties) {
            return new Chain>(U.findWhere(value(), properties));
        }

        public Chain uniq() {
            return new Chain(U.uniq(value()));
        }

        public  Chain uniq(final Function func) {
            return new Chain(U.newArrayList(U.uniq(value(), func)));
        }

        public Chain distinct() {
            return new Chain(U.uniq(value()));
        }

        @SuppressWarnings("unchecked")
        public  Chain distinctBy(final Function func) {
            return new Chain(U.newArrayList((Iterable) U.uniq(value(), func)));
        }

        @SuppressWarnings("unchecked")
        public Chain union(final List ... lists) {
            return new Chain(U.union(value(), lists));
        }

        @SuppressWarnings("unchecked")
        public Chain intersection(final List ... lists) {
            return new Chain(U.intersection(value(), lists));
        }

        @SuppressWarnings("unchecked")
        public Chain difference(final List ... lists) {
            return new Chain(U.difference(value(), lists));
        }

        public Chain range(final int stop) {
            return new Chain(U.range(stop));
        }

        public Chain range(final int start, final int stop) {
            return new Chain(U.range(start, stop));
        }

        public Chain range(final int start, final int stop, final int step) {
            return new Chain(U.range(start, stop, step));
        }

        public Chain> chunk(final int size) {
            return new Chain>(U.chunk(value(), size, size));
        }

        public Chain> chunk(final int size, final int step) {
            return new Chain>(U.chunk(value(), size, step));
        }

        public Chain> chunkFill(final int size, final T fillValue) {
            return new Chain>(U.chunkFill(value(), size, size, fillValue));
        }

        public Chain> chunkFill(final int size, final int step, final T fillValue) {
            return new Chain>(U.chunkFill(value(), size, step, fillValue));
        }

        public Chain cycle(final int times) {
            return new Chain(U.cycle(value(), times));
        }

        public Chain interpose(final T element) {
            return new Chain(U.interpose(value(), element));
        }

        public Chain interposeByList(final Iterable interIter) {
            return new Chain(U.interposeByList(value(), interIter));
        }

        @SuppressWarnings("unchecked")
        public Chain concat(final List ... lists) {
            return new Chain(U.concat(value(), lists));
        }

        public Chain slice(final int start) {
            return new Chain(U.slice(value(), start));
        }

        public Chain slice(final int start, final int end) {
            return new Chain(U.slice(value(), start, end));
        }

        public Chain reverse() {
            return new Chain(U.reverse(value()));
        }

        public Chain join() {
            return new Chain(U.join(value()));
        }

        public Chain join(final String separator) {
            return new Chain(U.join(value(), separator));
        }

        public Chain skip(final int numberToSkip) {
            return new Chain(value().subList(numberToSkip, value().size()));
        }

        public Chain limit(final int size) {
            return new Chain(value().subList(0, size));
        }

        @SuppressWarnings("unchecked")
        public  Chain> toMap() {
            return new Chain>(U.toMap((Iterable>) value()));
        }

        public Chain drop() {
            return new Chain(U.drop(value()));
        }

        public Chain drop(final Integer n) {
            return new Chain(U.drop(value(), n));
        }

        public Chain dropRight() {
            return new Chain(U.dropRight(value()));
        }

        public Chain dropRight(final Integer n) {
            return new Chain(U.dropRight(value(), n));
        }

        public Chain dropWhile(final Predicate pred) {
            return new Chain(U.dropWhile(value(), pred));
        }

        public Chain dropRightWhile(final Predicate pred) {
            return new Chain(U.dropRightWhile(value(), pred));
        }

        @SuppressWarnings("unchecked")
        public Chain fill(final Object value) {
            return new Chain(U.fill((List) value(), value));
        }

        @SuppressWarnings("unchecked")
        public Chain fill(final Object value, final Integer start, final Integer end) {
            return new Chain(U.fill((List) value(), value, start, end));
        }

        public Chain flattenDeep() {
            return new Chain(U.flattenDeep(value()));
        }

        @SuppressWarnings("unchecked")
        public Chain pull(final Object ... values) {
            return new Chain(U.pull((List) value(), values));
        }

        @SuppressWarnings("unchecked")
        public Chain pullAt(final Integer ... indexes) {
            return new Chain(U.pullAt((List) value(), indexes));
        }

        public Chain remove(final Predicate pred) {
            return new Chain(U.remove(value(), pred));
        }

        public Chain take() {
            return new Chain(U.take(value()));
        }

        public Chain takeRight() {
            return new Chain(U.takeRight(value()));
        }

        public Chain take(final Integer n) {
            return new Chain(U.take(value(), n));
        }

        public Chain takeRight(final Integer n) {
            return new Chain(U.takeRight(value(), n));
        }

        public Chain takeWhile(final Predicate pred) {
            return new Chain(U.takeWhile(value(), pred));
        }

        public Chain takeRightWhile(final Predicate pred) {
            return new Chain(U.takeRightWhile(value(), pred));
        }

        @SuppressWarnings("unchecked")
        public Chain xor(final List list) {
            return new Chain(U.xor(value(), list));
        }

        public Chain at(final Integer ... indexes) {
            return new Chain(U.at(value(), indexes));
        }

        @SuppressWarnings("unchecked")
        public  Chain sum() {
            return new Chain(U.sum((List) value()));
        }

        public  Chain sum(final Function func) {
            return new Chain(U.sum(value(), func));
        }

        @SuppressWarnings("unchecked")
        public Chain mean() {
            return new Chain(U.mean((List) value()));
        }

        @SuppressWarnings("unchecked")
        public Chain median() {
            return new Chain(U.median((List) value()));
        }

        public Chain camelCase() {
            return new Chain(U.camelCase((String) item()));
        }

        public Chain lowerFirst() {
            return new Chain(U.lowerFirst((String) item()));
        }

        public Chain upperFirst() {
            return new Chain(U.upperFirst((String) item()));
        }

        public Chain capitalize() {
            return new Chain(U.capitalize((String) item()));
        }

        public Chain deburr() {
            return new Chain(U.deburr((String) item()));
        }

        public Chain endsWith(final String target) {
            return new Chain(U.endsWith((String) item(), target));
        }

        public Chain endsWith(final String target, final Integer position) {
            return new Chain(U.endsWith((String) item(), target, position));
        }

        public Chain kebabCase() {
            return new Chain(U.kebabCase((String) item()));
        }

        public Chain repeat(final int length) {
            return new Chain(U.repeat((String) item(), length));
        }

        public Chain pad(final int length) {
            return new Chain(U.pad((String) item(), length));
        }

        public Chain pad(final int length, final String chars) {
            return new Chain(U.pad((String) item(), length, chars));
        }

        public Chain padStart(final int length) {
            return new Chain(U.padStart((String) item(), length));
        }

        public Chain padStart(final int length, final String chars) {
            return new Chain(U.padStart((String) item(), length, chars));
        }

        public Chain padEnd(final int length) {
            return new Chain(U.padEnd((String) item(), length));
        }

        public Chain padEnd(final int length, final String chars) {
            return new Chain(U.padEnd((String) item(), length, chars));
        }

        public Chain snakeCase() {
            return new Chain(U.snakeCase((String) item()));
        }

        public Chain startCase() {
            return new Chain(U.startCase((String) item()));
        }

        public Chain startsWith(final String target) {
            return new Chain(U.startsWith((String) item(), target));
        }

        public Chain startsWith(final String target, final Integer position) {
            return new Chain(U.startsWith((String) item(), target, position));
        }

        public Chain trim() {
            return new Chain(U.trim((String) item()));
        }

        public Chain trim(final String chars) {
            return new Chain(U.trim((String) item(), chars));
        }

        public Chain trimStart() {
            return new Chain(U.trimStart((String) item()));
        }

        public Chain trimStart(final String chars) {
            return new Chain(U.trimStart((String) item(), chars));
        }

        public Chain trimEnd() {
            return new Chain(U.trimEnd((String) item()));
        }

        public Chain trunc() {
            return new Chain(U.trunc((String) item()));
        }

        public Chain trunc(final int length) {
            return new Chain(U.trunc((String) item(), length));
        }

        public Chain trimEnd(final String chars) {
            return new Chain(U.trimEnd((String) item(), chars));
        }

        public Chain uncapitalize() {
            return new Chain(U.uncapitalize((String) item()));
        }

        public Chain words() {
            return new Chain(U.words((String) item()));
        }

        public Chain toJson() {
            return new Chain(Json.toJson((Collection) value()));
        }

        public Chain fromJson() {
            return new Chain(Json.fromJson((String) item()));
        }

        public Chain toXml() {
            return new Chain(Xml.toXml((Collection) value()));
        }

        public Chain fromXml() {
            return new Chain(Xml.fromXml((String) item()));
        }

        public Chain fetch() {
            return new Chain(U.fetch((String) item()).text());
        }

        public Chain fetch(final String method, final String body) {
            return new Chain(U.fetch((String) item(), method, body).text());
        }

        public Chain> createPermutationWithRepetition(final int permutationLength) {
            return new Chain>(U.createPermutationWithRepetition((List) value(), permutationLength));
        }

        public Chain toJsonJavaString() {
            return new Chain(Json.toJsonJavaString((Collection) value()));
        }

        public Chain xmlToJson() {
            return new Chain(U.xmlToJson((String) item()));
        }

        public Chain jsonToXml() {
            return new Chain(U.jsonToXml((String) item()));
        }
    }

    public static Chain chain(final String item) {
        return new U.Chain(item);
    }

    public static  Chain chain(final List list) {
        return new U.Chain(list);
    }

    public static  Chain chain(final Iterable iterable) {
        return new U.Chain(newArrayList(iterable));
    }

    public static  Chain chain(final Iterable iterable, int size) {
        return new U.Chain(newArrayList(iterable, size));
    }

    @SuppressWarnings("unchecked")
    public static  Chain chain(final T ... list) {
        return new U.Chain(Arrays.asList(list));
    }

    public static Chain chain(final int[] array) {
        return new U.Chain(newIntegerList(array));
    }

    public Chain chain() {
        return new U.Chain(newArrayList(value()));
    }

    public static Chain of(final String item) {
        return new U.Chain(item);
    }

    public static  Chain of(final List list) {
        return new U.Chain(list);
    }

    public static  Chain of(final Iterable iterable) {
        return new U.Chain(newArrayList(iterable));
    }

    public static  Chain of(final Iterable iterable, int size) {
        return new U.Chain(newArrayList(iterable, size));
    }

    @SuppressWarnings("unchecked")
    public static  Chain of(final T ... list) {
        return new U.Chain(Arrays.asList(list));
    }

    public static Chain of(final int[] array) {
        return new U.Chain(newIntegerList(array));
    }

    public Chain of() {
        return new U.Chain(newArrayList(value()));
    }

    public static  List drop(final Iterable iterable) {
        return rest(newArrayList(iterable));
    }

    public List drop() {
        return drop(getIterable());
    }

    public static  List drop(final Iterable iterable, final Integer n) {
        return rest(newArrayList(iterable), n);
    }

    public List drop(final Integer n) {
        return drop(getIterable(), n);
    }

    public static  List dropRight(final Iterable iterable) {
        return initial(newArrayList(iterable));
    }

    public List dropRight() {
        return dropRight(getIterable());
    }

    public static  List dropRight(final Iterable iterable, final Integer n) {
        return initial(newArrayList(iterable), n);
    }

    public List dropRight(final Integer n) {
        return dropRight(getIterable(), n);
    }

    public static  List dropWhile(final Iterable iterable, final Predicate pred) {
        return rest(newArrayList(iterable), findIndex(newArrayList(iterable), negate(pred)));
    }

    public List dropWhile(final Predicate pred) {
        return dropWhile(getIterable(), pred);
    }

    public static  List dropRightWhile(final Iterable iterable, final Predicate pred) {
        return reverse(dropWhile(reverse(iterable), pred));
    }

    public List dropRightWhile(final Predicate pred) {
        return dropRightWhile(getIterable(), pred);
    }

    public static  List fill(List list, T item) {
        for (int i = 0; i < size(list); i++) {
            list.set(i, item);
        }
        return list;
    }

    public static  T[] fill(T[] array, T item) {
        for (int i = 0; i < array.length; i++) {
             array[i] = item;
        }
        return array;
    }

    @SuppressWarnings("unchecked")
    public List fill(Object value) {
        return fill((List) getIterable(), value);
    }

    public static List fill(final List list, Object value, Integer start, Integer end) {
        for (int index = start; index < end; index += 1) {
            list.set(index, value);
        }
        return list;
    }

    @SuppressWarnings("unchecked")
    public List fill(Object value, Integer start, Integer end) {
        return fill((List) getIterable(), value, start, end);
    }

    public static  List flattenDeep(final List list) {
        return flatten(list, false);
    }

    public List flattenDeep() {
        return flattenDeep((List) getIterable());
    }

    public static List pull(final List list, Object ... values) {
        final List valuesList = Arrays.asList(values);
        for (final Iterator iterator = list.iterator(); iterator.hasNext(); ) {
            final Object object = iterator.next();
            if (valuesList.contains(object)) {
                iterator.remove();
            }
        }
        return list;
    }

    @SuppressWarnings("unchecked")
    public List pull(Object ... values) {
        return pull((List) getIterable(), values);
    }

    public static List pullAt(final List list, final Integer ... indexes) {
        final List result = newArrayList();
        final List indexesList = Arrays.asList(indexes);
        int index = 0;
        for (final Iterator iterator = list.iterator(); iterator.hasNext(); ) {
            final Object object = iterator.next();
            if (indexesList.contains(index)) {
                result.add(object);
                iterator.remove();
            }
            index += 1;
        }
        return result;
    }

    @SuppressWarnings("unchecked")
    public List pullAt(final Integer ... indexes) {
        return pullAt((List) getIterable(), indexes);
    }

    public static  List remove(final List list, final Predicate pred) {
        final List result = newArrayList();
        for (final Iterator iterator = list.iterator(); iterator.hasNext(); ) {
            final T object = iterator.next();
            if (pred.test(object)) {
                result.add(object);
                iterator.remove();
            }
        }
        return result;
    }

    public List remove(final Predicate pred) {
        return remove((List) getIterable(), pred);
    }

    public static  List take(final Iterable iterable) {
        return first(newArrayList(iterable), 1);
    }

    public List take() {
        return take(getIterable());
    }

    public static  List takeRight(final Iterable iterable) {
        return last(newArrayList(iterable), 1);
    }

    public List takeRight() {
        return takeRight(getIterable());
    }

    public static  List take(final Iterable iterable, final Integer n) {
        return first(newArrayList(iterable), n);
    }

    public List take(final Integer n) {
        return take(getIterable(), n);
    }

    public static  List takeRight(final Iterable iterable, final Integer n) {
        return last(newArrayList(iterable), n);
    }

    public List takeRight(final Integer n) {
        return takeRight(getIterable(), n);
    }

    public static  List takeWhile(final Iterable iterable, final Predicate pred) {
        return first(newArrayList(iterable), findIndex(newArrayList(iterable), negate(pred)));
    }

    public List takeWhile(final Predicate pred) {
        return takeWhile(getIterable(), pred);
    }

    public static  List takeRightWhile(final Iterable iterable, final Predicate pred) {
        return reverse(takeWhile(reverse(iterable), pred));
    }

    public List takeRightWhile(final Predicate pred) {
        return takeRightWhile(getIterable(), pred);
    }

    @SuppressWarnings("unchecked")
    public static  List xor(final List ... lists) {
        int index = -1;
        int length = lists.length;
        List result = null;
        while (++index < length) {
            final List array = lists[index];
            result = result == null ? array : concat(difference(result, array), difference(array, result));
        }
        return uniq(result);
    }

    @SuppressWarnings("unchecked")
    public List xor(final List list) {
        return xor((List) getIterable(), list);
    }

    public static  List at(final List list, final Integer ... indexes) {
        final List result = newArrayList();
        final List indexesList = Arrays.asList(indexes);
        int index = 0;
        for (final T object : list) {
            if (indexesList.contains(index)) {
                result.add(object);
            }
            index += 1;
        }
        return result;
    }

    public List at(final Integer ... indexes) {
        return at((List) getIterable(), indexes);
    }

    public static  Double average(final Iterable iterable) {
        T sum = sum(iterable);
        if (sum == null) {
            return null;
        }
        return sum.doubleValue() / size(iterable);
    }

    public static  Double average(final Iterable iterable, final Function func) {
        F sum = sum(iterable, func);
        if (sum == null) {
            return null;
        }
        return sum.doubleValue() / size(iterable);
    }

    public static  Double average(N[] array) {
        N sum = sum(array);
        if (sum == null) {
            return null;
        }
        return sum.doubleValue() / array.length;
    }

    public static Double average(java.math.BigDecimal first, java.math.BigDecimal second) {
        if (first == null || second == null) {
            return null;
        }
        return sum(first, second).doubleValue() / 2;
    }

    public static Double average(java.math.BigInteger first, java.math.BigInteger second) {
        if (first == null || second == null) {
            return null;
        }
      return sum(first, second).doubleValue() / 2;
    }

    public static Double average(Byte first, Byte second) {
        if (first == null || second == null) {
            return null;
        }
        return sum(first, second).doubleValue() / 2;
    }

    public static Double average(Double first, Double second) {
        if (first == null || second == null) {
            return null;
        }
        return sum(first, second) / 2;
    }

    public static Double average(Float first, Float second) {
        if (first == null || second == null) {
            return null;
        }
        return sum(first, second).doubleValue() / 2;
    }

    public static Double average(Integer first, Integer second) {
        if (first == null || second == null) {
            return null;
        }
        return sum(first, second).doubleValue() / 2;
    }

    public static Double average(Long first, Long second) {
        if (first == null || second == null) {
            return null;
        }
        return sum(first, second).doubleValue() / 2;
    }

    public static  T sum(final Iterable iterable) {
        T result = null;
        for (final T item : iterable) {
            result = add(result, item);
        }
        return result;
    }

    public static  F sum(final Iterable iterable, final Function func) {
        F result = null;
        for (final E item : iterable) {
            result = add(result, func.apply(item));
        }
        return result;
    }

    public static  N sum(N[] array) {
        N result = null;
        for (final N item : array) {
            result = add(result, item);
        }
        return result;
    }

    @SuppressWarnings("unchecked")
    public  F sum() {
        return sum((List) getIterable());
    }

    @SuppressWarnings("unchecked")
    public  F sum(final Function func) {
        return sum((List) getIterable(), func);
    }

    @SuppressWarnings("unchecked")
    public static  T add(final T first, final T second) {
        if (first == null) {
            return second;
        } else if (second == null) {
            return first;
        } else if (first instanceof java.math.BigDecimal) {
            return (T) sum((java.math.BigDecimal) first, (java.math.BigDecimal) second);
        } else if (second instanceof java.math.BigInteger) {
            return (T) sum((java.math.BigInteger) first, (java.math.BigInteger) second);
        } else if (first instanceof Byte) {
            return (T) sum((Byte) first, (Byte) second);
        } else if (first instanceof Double) {
            return (T) sum((Double) first, (Double) second);
        } else if (first instanceof Float) {
            return (T) sum((Float) first, (Float) second);
        } else if (first instanceof Integer) {
            return (T) sum((Integer) first, (Integer) second);
        } else if (first instanceof Long) {
            return (T) sum((Long) first, (Long) second);
        } else if (first instanceof Short) {
            return (T) sum((Short) first, (Short) second);
        } else {
            throw new UnsupportedOperationException("Sum only supports official subclasses of Number");
        }
    }

    private static java.math.BigDecimal sum(java.math.BigDecimal first, java.math.BigDecimal second) {
        return first.add(second);
    }

    private static java.math.BigInteger sum(java.math.BigInteger first, java.math.BigInteger second) {
        return first.add(second);
    }

    private static Byte sum(Byte first, Byte second) {
        return (byte) (first + second);
    }

    private static Double sum(Double first, Double second) {
        return first + second;
    }

    private static Float sum(Float first, Float second) {
        return first + second;
    }

    private static Integer sum(Integer first, Integer second) {
        return first + second;
    }

    private static Long sum(Long first, Long second) {
        return first + second;
    }

    private static Short sum(Short first, Short second) {
        return (short) (first + second);
    }

    @SuppressWarnings("unchecked")
    public static  T subtract(final T ... values) {
        if (values.length == 0) {
            return null;
        }
        T result = values[0];
        for (int i = 1; i < values.length; i++) {
            if (result instanceof java.math.BigDecimal) {
                java.math.BigDecimal value = (java.math.BigDecimal) values[i];
                result = add(result, (T) value.negate());
            } else if (result instanceof java.math.BigInteger) {
                java.math.BigInteger value = (java.math.BigInteger) values[i];
                result = add(result, (T) value.negate());
            } else if (result instanceof Byte) {
                result = add(result, (T) Byte.valueOf((byte) (values[i].byteValue() * -1)));
            } else if (result instanceof Double) {
                result = add(result, (T) Double.valueOf(values[i].doubleValue() * -1));
            } else if (result instanceof Float) {
                result = add(result, (T) Float.valueOf(values[i].floatValue() * -1));
            } else if (result instanceof Integer) {
                result = add(result, (T) Integer.valueOf(values[i].intValue() * -1));
            } else if (result instanceof Long) {
                result = add(result, (T) Long.valueOf(values[i].longValue() * -1));
            } else if (result instanceof Short) {
                result = add(result, (T) Short.valueOf((short) (values[i].shortValue() * -1)));
            } else {
                throw new UnsupportedOperationException("Subtract only supports official subclasses of Number");
            }
        }
        return result;
    }

    public static  double mean(final Iterable iterable) {
        T result = null;
        int count = 0;
        for (final T item : iterable) {
            result = add(result, item);
            count += 1;
        }
        if (result == null) {
            return 0d;
        }
        return result.doubleValue() / count;
    }

    @SuppressWarnings("unchecked")
    public double mean() {
        return mean((Iterable) getIterable());
    }

    @SuppressWarnings("unchecked")
    public static  double median(final Iterable iterable) {
        final List result = newArrayList((Collection) iterable);
        final int size = size(iterable);
        if (size == 0) {
            throw new IllegalArgumentException("Iterable cannot be empty");
        }
        if (size % 2 != 0) {
            return result.get(size / 2).doubleValue();
        }
        return (result.get(size / 2 - 1).doubleValue() + result.get(size / 2).doubleValue()) / 2;
    }

    @SuppressWarnings("unchecked")
    public double median() {
        return median((Iterable) getIterable());
    }

    public static String camelCase(final String string) {
        return createCompounder(new Function3() {
            public String apply(final String result, final String word, final Integer index) {
                final String localWord = word.toLowerCase(Locale.getDefault());
                return result + (index > 0 ? localWord.substring(0, 1).toUpperCase(Locale.getDefault())
                    + localWord.substring(1) : localWord);
            }
        }).apply(string);
    }

    public static String lowerFirst(final String string) {
        return createCaseFirst("toLowerCase").apply(string);
    }

    public static String upperFirst(final String string) {
        return createCaseFirst("toUpperCase").apply(string);
    }

    public static String capitalize(final String string) {
        return upperFirst(baseToString(string));
    }

    public static String uncapitalize(final String string) {
        return lowerFirst(baseToString(string));
    }

    private static String baseToString(String value) {
        return value == null ? "" : value;
    }

    public static String deburr(final String string) {
        final String localString = baseToString(string);
        final StringBuilder sb = new StringBuilder();
        for (final String str : localString.split("")) {
            if (RE_LATIN_1.matcher(str).matches()) {
                sb.append(DEBURRED_LETTERS.get(str));
            } else {
                sb.append(str);
            }
        }
        return sb.toString();
    }

    public static List words(final String string) {
        final String localString = baseToString(string);
        final List result = new ArrayList();
        final java.util.regex.Matcher matcher = reWords.matcher(localString);
        while (matcher.find()) {
            result.add(matcher.group());
        }
        return result;
    }

    private static Function createCompounder(
        final Function3 callback) {
        return new Function() {
            public String apply(final String string) {
                int index = -1;
                List array = words(deburr(string));
                int length = array.size();
                String result = "";

                while (++index < length) {
                    result = callback.apply(result, array.get(index), index);
                }
                return result;
            }
        };
    }

    private static Function createCaseFirst(final String methodName) {
        return new Function() {
            public String apply(final String string) {
                final String localString = baseToString(string);
                final String chr = localString.isEmpty() ? "" : localString.substring(0, 1);
                final String trailing = localString.length() > 1 ? localString.substring(1) : "";
                return U.invoke(Collections.singletonList(chr), methodName).get(0) + trailing;
            }
        };
    }

    public static boolean endsWith(final String string, final String target) {
        return endsWith(string, target, null);
    }

    public static boolean endsWith(final String string, final String target, final Integer position) {
        if (string == null || target == null) {
            return false;
        }
        final String localString = baseToString(string);

        final int length = localString.length();
        final int fixedPosition = position == null || position < 0 ? 0 : position;
        final int localPosition = position == null ? length : Math.min(fixedPosition, length);

        final int localPosition2 = localPosition - target.length();
        return localPosition2 >= 0 && localString.indexOf(target, localPosition2) == localPosition2;
    }

    public static String kebabCase(final String string) {
        return createCompounder(new Function3() {
            public String apply(final String result, final String word, final Integer index) {
                return result + (index > 0 ? "-" : "") + word.toLowerCase(Locale.getDefault());
            }
        }).apply(string);
    }

    public static String repeat(final String string, final int length) {
        final StringBuilder result = new StringBuilder();
        final StringBuilder localString = new StringBuilder(baseToString(string));
        if (length < 1 || string == null) {
            return result.toString();
        }
        int n = length;
        do {
            if (n % 2 != 0) {
                result.append(localString);
            }
            n = (int) Math.floor(n / (double) 2);
            localString.append(localString.toString());
        } while (n > 0);
        return result.toString();
    }

    private static String createPadding(final String string, final int length, final String chars) {
        final int strLength = string.length();
        final int padLength = length - strLength;
        final String localChars = chars == null ? " " : chars;
        return repeat(localChars, (int) Math.ceil(padLength / (double) localChars.length())).substring(0, padLength);
    }

    public static String pad(final String string, final int length) {
        return pad(string, length, null);
    }

    public static String pad(final String string, final int length, final String chars) {
        final String localString = baseToString(string);
        final int strLength = localString.length();
        if (strLength >= length) {
            return localString;
        }
        final double mid = (length - strLength) / (double) 2;
        final int leftLength = (int) Math.floor(mid);
        final int rightLength = (int) Math.ceil(mid);
        final String localChars = createPadding("", rightLength, chars);
        return localChars.substring(0, leftLength) + localString + localChars;
    }

    private static Function3 createPadDir(final boolean fromRight) {
        return new Function3() {
            public String apply(String string, Integer length, String chars) {
                final String localString = baseToString(string);
                return (fromRight ? localString : "") + createPadding(localString, length, chars)
                    + (fromRight ? "" : localString);
            }
        };
    }

    public static String padStart(final String string, final Integer length) {
        return createPadDir(false).apply(string, length, null);
    }

    public static String padStart(final String string, final Integer length, final String chars) {
        return createPadDir(false).apply(string, length, chars);
    }

    public static String padEnd(final String string, final Integer length) {
        return createPadDir(true).apply(string, length, null);
    }

    public static String padEnd(final String string, final Integer length, final String chars) {
        return createPadDir(true).apply(string, length, chars);
    }

    public static String snakeCase(final String string) {
        return createCompounder(new Function3() {
            public String apply(final String result, final String word, final Integer index) {
                return result + (index > 0 ? "_" : "") + word.toLowerCase(Locale.getDefault());
            }
        }).apply(string);
    }

    public static String startCase(final String string) {
        return createCompounder(new Function3() {
            public String apply(final String result, final String word, final Integer index) {
                return result + (index > 0 ? " " : "") + word.substring(0, 1).toUpperCase(Locale.getDefault())
                    + word.substring(1);
            }
        }).apply(string);
    }

    public static boolean startsWith(final String string, final String target) {
        return startsWith(string, target, null);
    }

    public static boolean startsWith(final String string, final String target, final Integer position) {
        if (string == null || target == null) {
            return false;
        }
        final String localString = baseToString(string);

        final int length = localString.length();
        final int localPosition = position == null ? 0
            : Math.min(position < 0 ? 0 : position, length);

        return localString.lastIndexOf(target, localPosition) == localPosition;
    }

    private static int charsLeftIndex(final String string, final String chars) {
        int index = 0;
        final int length = string.length();
        while (index < length && chars.indexOf(string.charAt(index)) > -1) {
            index += 1;
        }
        return index == length ? -1 : index;
    }

    private static int charsRightIndex(final String string, final String chars) {
        int index = string.length() - 1;
        while (index >= 0 && chars.indexOf(string.charAt(index)) > -1) {
            index -= 1;
        }
        return index;
    }

    public static String trim(final String string) {
        return trim(string, null);
    }

    public static String trim(final String string, final String chars) {
        final String localString = baseToString(string);
        if (localString.isEmpty()) {
            return localString;
        }
        final String localChars;
        if (chars == null) {
            localChars = " ";
        } else {
            localChars = chars;
        }
        final int leftIndex = charsLeftIndex(localString, localChars);
        final int rightIndex = charsRightIndex(localString, localChars);
        return leftIndex > -1 ? localString.substring(leftIndex, rightIndex + 1) : localString;
    }

    public static String trimStart(final String string) {
        return trimStart(string, null);
    }

    public static String trimStart(final String string, final String chars) {
        final String localString = baseToString(string);
        if (localString.isEmpty()) {
            return localString;
        }
        final String localChars;
        if (chars == null) {
            localChars = " ";
        } else {
            localChars = chars;
        }
        final int leftIndex = charsLeftIndex(localString, localChars);
        return leftIndex > -1 ? localString.substring(leftIndex) : localString;
    }

    public static String trimEnd(final String string) {
        return trimEnd(string, null);
    }

    public static String trimEnd(final String string, final String chars) {
        final String localString = baseToString(string);
        if (localString.isEmpty()) {
            return localString;
        }
        final String localChars;
        if (chars == null) {
            localChars = " ";
        } else {
            localChars = chars;
        }
        final int rightIndex = charsRightIndex(localString, localChars);
        return rightIndex > -1 ? localString.substring(0, rightIndex + 1) : localString;
    }

    public static String trunc(final String string) {
        return trunc(string, DEFAULT_TRUNC_LENGTH);
    }

    public static String trunc(final String string, final Integer length) {
        final String localString = baseToString(string);
        final String omission = DEFAULT_TRUNC_OMISSION;
        if (length >= localString.length()) {
            return localString;
        }
        final int end = length - omission.length();
        final String result = localString.substring(0, end);
        return result + omission;
    }

    public static List stringToPath(final String string) {
        final List result = new ArrayList();
        final java.util.regex.Matcher matcher = RE_PROP_NAME.matcher(baseToString(string));
        while (matcher.find()) {
            result.add(matcher.group(1) == null ? matcher.group(0) : matcher.group(1));
        }
        return result;
    }

    @SuppressWarnings("unchecked")
    private static  T baseGetAndSet(final Map object, final String path,
        final Optional value) {
        final List paths = stringToPath(path);
        int index = 0;
        final int length = paths.size();

        Object localObject = object;
        Object savedLocalObject = null;
        String savedPath = null;
        while (localObject != null && index < length) {
            if (localObject instanceof Map) {
                Map.Entry mapEntry = getMapEntry((Map) localObject);
                if (mapEntry != null && "#item".equals(mapEntry.getKey())) {
                    localObject = mapEntry.getValue();
                    continue;
                }
                savedLocalObject = localObject;
                savedPath = paths.get(index);
                localObject = ((Map) localObject).get(paths.get(index));
            } else if (localObject instanceof List) {
                savedLocalObject = localObject;
                savedPath = paths.get(index);
                localObject = ((List) localObject).get(Integer.parseInt(paths.get(index)));
            } else {
                break;
            }
            index += 1;
        }
        if (index > 0 && index == length) {
            if (value.isPresent()) {
                if (savedLocalObject instanceof Map) {
                    ((Map) savedLocalObject).put(savedPath, value.get());
                } else {
                    ((List) savedLocalObject).set(Integer.parseInt(savedPath), value.get());
                }
            }
            return (T) localObject;
        }
        return null;
    }

    private static Map.Entry getMapEntry(Map map) {
        return map.isEmpty() ? null : (Map.Entry) map.entrySet().iterator().next();
    }

    public static  T get(final Map object, final String path) {
        return baseGetAndSet(object, path, Optional.absent());
    }

    public static  T set(final Map object, final String path, Object value) {
        return baseGetAndSet(object, path, Optional.of(value));
    }

    @SuppressWarnings("unchecked")
    public static Map remove(final Map map, final String key) {
        Map outMap = newLinkedHashMap();
        for (Map.Entry entry : map.entrySet()) {
            if (!entry.getKey().equals(key)) {
                outMap.put(entry.getKey(), makeObjectForRemove(entry.getValue(), key));
            }
        }
        return outMap;
    }

    @SuppressWarnings("unchecked")
    private static Object makeObjectForRemove(Object value, final String key) {
        final Object result;
        if (value instanceof List) {
            List values = newArrayList();
            for (Object item : (List) value) {
                values.add(item instanceof Map ? remove((Map) item, key) : item);
            }
            result = values;
        } else if (value instanceof Map) {
            result = remove((Map) value, key);
        } else {
            result = value;
        }
        return result;
    }

    @SuppressWarnings("unchecked")
    public static Map rename(final Map map, final String oldKey, final String newKey) {
        Map outMap = newLinkedHashMap();
        for (Map.Entry entry : map.entrySet()) {
            if (entry.getKey().equals(oldKey)) {
                outMap.put(newKey, makeObjectForRename(entry.getValue(), oldKey, newKey));
            } else {
                outMap.put(entry.getKey(), makeObjectForRename(entry.getValue(), oldKey, newKey));
            }
        }
        return outMap;
    }

    @SuppressWarnings("unchecked")
    private static Object makeObjectForRename(Object value, final String oldKey, final String newKey) {
        final Object result;
        if (value instanceof List) {
            List values = newArrayList();
            for (Object item : (List) value) {
                values.add(item instanceof Map ? rename((Map) item, oldKey, newKey) : item);
            }
            result = values;
        } else if (value instanceof Map) {
            result = rename((Map) value, oldKey, newKey);
        } else {
            result = value;
        }
        return result;
    }

    public static Map setValue(final Map map, final String key,
        final Object newValue) {
        return setValue(map, key, new BiFunction() {
            public Object apply(String key, Object value) { return newValue; } });
    }

    public static Map setValue(final Map map, final String key,
        final BiFunction newValue) {
        Map outMap = newLinkedHashMap();
        for (Map.Entry entry : map.entrySet()) {
            if (entry.getKey().equals(key)) {
                outMap.put(key, makeObjectForSetValue(newValue.apply(key, entry.getValue()), key, newValue));
            } else {
                outMap.put(entry.getKey(), makeObjectForSetValue(entry.getValue(), key, newValue));
            }
        }
        return outMap;
    }

    @SuppressWarnings("unchecked")
    private static Object makeObjectForSetValue(Object value, final String key,
        final BiFunction newValue) {
        final Object result;
        if (value instanceof List) {
            List values = newArrayList();
            for (Object item : (List) value) {
                values.add(item instanceof Map ? setValue((Map) item, key, newValue) : item);
            }
            result = values;
        } else if (value instanceof Map) {
            result = setValue((Map) value, key, newValue);
        } else {
            result = value;
        }
        return result;
    }

    @SuppressWarnings("unchecked")
    public static Map update(final Map map1, final Map map2) {
        Map outMap = newLinkedHashMap();
        for (Map.Entry entry : map2.entrySet()) {
            String key = entry.getKey();
            Object value2 = entry.getValue();
            if (map1.containsKey(key)) {
                Object value1 = map1.get(key);
                if (value1 instanceof Map && value2 instanceof Map) {
                    outMap.put(key, update((Map) value1, (Map) value2));
                } else if (value1 instanceof List && value2 instanceof List) {
                    outMap.put(key, merge((List) value1, (List) value2));
                } else if (value1 instanceof List) {
                    outMap.put(key, merge((List) value1, newArrayList(value2)));
                } else if (value2 instanceof List) {
                    outMap.put(key, merge(newArrayList(value1), (List) value2));
                } else {
                    outMap.put(key, value2);
                }
            } else {
                outMap.put(key, value2);
            }
        }
        return outMap;
    }

    public static List merge(List list1, List list2) {
        List outList1 = newArrayList(list1);
        List outList2 = newArrayList(list2);
        outList2.removeAll(list1);
        outList1.addAll(outList2);
        return outList1;
    }

    public static class FetchResponse {
        private final boolean ok;
        private final int status;
        private final Map> headerFields;
        private final java.io.ByteArrayOutputStream stream;

        public FetchResponse(final boolean ok, final int status, final Map> headerFields,
            final java.io.ByteArrayOutputStream stream) {
            this.ok = ok;
            this.status = status;
            this.stream = stream;
            this.headerFields = headerFields;
        }

        public boolean isOk() {
            return ok;
        }

        public int getStatus() {
            return status;
        }

        public Map> getHeaderFields() {
            return headerFields;
        }

        public byte[] blob() {
            return stream.toByteArray();
        }

        public String text() {
            try {
                return stream.toString("UTF-8");
            } catch (java.io.UnsupportedEncodingException ex) {
                throw new UnsupportedOperationException(ex);
            }
        }

        public Object json() {
            return Json.fromJson(text());
        }

        public Object xml() {
            return Xml.fromXml(text());
        }
    }

    public static FetchResponse fetch(final String url) {
        return fetch(url, null, null, DEFAULT_HEADER_FIELDS, null, null);
    }

    public static FetchResponse fetch(final String url, final Integer connectTimeout, final Integer readTimeout) {
        return fetch(url, null, null, DEFAULT_HEADER_FIELDS, connectTimeout, readTimeout);
    }

    public static FetchResponse fetch(final String url, final String method, final String body) {
        return fetch(url, method, body, DEFAULT_HEADER_FIELDS, null, null);
    }

    private static class BaseHttpSslSocketFactory extends javax.net.ssl.SSLSocketFactory {
        private javax.net.ssl.SSLContext getSslContext() {
            return createEasySslContext();
        }

        @Override
        public java.net.Socket createSocket(java.net.InetAddress arg0, int arg1, java.net.InetAddress arg2,
                        int arg3) throws java.io.IOException {
            return getSslContext().getSocketFactory().createSocket(arg0, arg1,
                                arg2, arg3);
        }

        @Override
        public java.net.Socket createSocket(String arg0, int arg1, java.net.InetAddress arg2, int arg3)
                throws java.io.IOException {
            return getSslContext().getSocketFactory().createSocket(arg0, arg1,
                    arg2, arg3);
        }

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

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

        @Override
        public String[] getSupportedCipherSuites() {
            return new String[]{};
        }

        @Override
        public String[] getDefaultCipherSuites() {
            return new String[]{};
        }

        @Override
        public java.net.Socket createSocket(java.net.Socket arg0, String arg1, int arg2, boolean arg3)
                throws java.io.IOException {
            return getSslContext().getSocketFactory().createSocket(arg0, arg1,
                    arg2, arg3);
        }

        private javax.net.ssl.SSLContext createEasySslContext() {
            try {
                javax.net.ssl.SSLContext context = javax.net.ssl.SSLContext.getInstance("SSL");
                context.init(null, new javax.net.ssl.TrustManager[] { MyX509TrustManager.manger }, null);
                return context;
            } catch (Exception ex) {
                throw new UnsupportedOperationException(ex);
            }
        }

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

            static MyX509TrustManager manger = new MyX509TrustManager();

            public MyX509TrustManager() {
            }

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

            public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) {
            }

            public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) {
            }
        }
    }

    static class NoHostnameVerifier implements javax.net.ssl.HostnameVerifier {
        public boolean verify(String hostname, javax.net.ssl.SSLSession session) {
            return true;
        }
    }

    private static void setupConnection(final java.net.HttpURLConnection connection, final String method,
        final Map> headerFields, final Integer connectTimeout, final Integer readTimeout)
        throws java.io.IOException {
        final String localMethod;
        if (SUPPORTED_HTTP_METHODS.contains(method)) {
            localMethod = method;
        } else {
            localMethod = "GET";
        }
        connection.setRequestMethod(localMethod);
        if (connectTimeout != null) {
            connection.setConnectTimeout(connectTimeout);
        }
        if (readTimeout != null) {
            connection.setReadTimeout(readTimeout);
        }
        if (connection instanceof javax.net.ssl.HttpsURLConnection) {
            ((javax.net.ssl.HttpsURLConnection) connection).setSSLSocketFactory(new BaseHttpSslSocketFactory());
            ((javax.net.ssl.HttpsURLConnection) connection).setHostnameVerifier(new NoHostnameVerifier());
        }
        if (headerFields != null) {
            for (final Map.Entry> header : headerFields.entrySet()) {
                connection.setRequestProperty(header.getKey(), join(header.getValue(), ";"));
            }
        }
    }

    public static FetchResponse fetch(final String url, final String method, final String body,
        final Map> headerFields, final Integer connectTimeout, final Integer readTimeout) {
        try {
            final java.net.URL localUrl = new java.net.URL(url);
            final java.net.HttpURLConnection connection = (java.net.HttpURLConnection) localUrl.openConnection();
            setupConnection(connection, method, headerFields, connectTimeout, readTimeout);
            if (body != null) {
                connection.setDoOutput(true);
                final java.io.DataOutputStream outputStream =
                    new java.io.DataOutputStream(connection.getOutputStream());
                outputStream.writeBytes(body);
                outputStream.close();
            }
            final int responseCode = connection.getResponseCode();
            final java.io.InputStream inputStream;
            if (responseCode < RESPONSE_CODE_400) {
                inputStream = connection.getInputStream();
            } else {
                inputStream = connection.getErrorStream();
            }
            final java.io.ByteArrayOutputStream result = new java.io.ByteArrayOutputStream();
            final byte[] buffer = new byte[BUFFER_LENGTH_1024];
            int length;
            while ((length = inputStream.read(buffer)) != -1) {
                result.write(buffer, 0, length);
            }
            inputStream.close();
            return new FetchResponse(responseCode < RESPONSE_CODE_400, responseCode, connection.getHeaderFields(),
                result);
        } catch (java.io.IOException ex) {
            throw new UnsupportedOperationException(ex);
        }
    }

    public static List explode(final String input) {
        List result = newArrayList();
        if (isNull(input)) {
            return result;
        }
        for (char character : input.toCharArray()) {
            result.add(String.valueOf(character));
        }
        return result;
    }

    public static String implode(final String[] input) {
        StringBuilder builder = new StringBuilder();
        for (String character : input) {
            if (nonNull(character)) {
                builder.append(character);
            }
        }
        return builder.toString();
    }

    public static String implode(final Iterable input) {
        StringBuilder builder = new StringBuilder();
        for (String character: input) {
            if (nonNull(character)) {
                builder.append(character);
            }
        }
        return builder.toString();
    }

    public String camelCase() {
        return camelCase(getString().get());
    }

    public String lowerFirst() {
        return lowerFirst(getString().get());
    }

    public String upperFirst() {
        return upperFirst(getString().get());
    }

    public String capitalize() {
        return capitalize(getString().get());
    }

    public String deburr() {
        return deburr(getString().get());
    }

    public boolean endsWith(final String target) {
        return endsWith(getString().get(), target);
    }

    public boolean endsWith(final String target, final Integer position) {
        return endsWith(getString().get(), target, position);
    }

    public String kebabCase() {
        return kebabCase(getString().get());
    }

    public String repeat(final int length) {
        return repeat(getString().get(), length);
    }

    public String pad(final int length) {
        return pad(getString().get(), length);
    }

    public String pad(final int length, final String chars) {
        return pad(getString().get(), length, chars);
    }

    public String padStart(final int length) {
        return padStart(getString().get(), length);
    }

    public String padStart(final int length, final String chars) {
        return padStart(getString().get(), length, chars);
    }

    public String padEnd(final int length) {
        return padEnd(getString().get(), length);
    }

    public String padEnd(final int length, final String chars) {
        return padEnd(getString().get(), length, chars);
    }

    public String snakeCase() {
        return snakeCase(getString().get());
    }

    public String startCase() {
        return startCase(getString().get());
    }

    public boolean startsWith(final String target) {
        return startsWith(getString().get(), target);
    }

    public boolean startsWith(final String target, final Integer position) {
        return startsWith(getString().get(), target, position);
    }

    public String trim() {
        return trim(getString().get());
    }

    public String trimWith(final String chars) {
        return trim(getString().get(), chars);
    }

    public String trimStart() {
        return trimStart(getString().get());
    }

    public String trimStartWith(final String chars) {
        return trimStart(getString().get(), chars);
    }

    public String trimEnd() {
        return trimEnd(getString().get());
    }

    public String trimEndWith(final String chars) {
        return trimEnd(getString().get(), chars);
    }

    public String trunc() {
        return trunc(getString().get());
    }

    public String trunc(final int length) {
        return trunc(getString().get(), length);
    }

    public String uncapitalize() {
        return uncapitalize(getString().get());
    }

    public List words() {
        return words(getString().get());
    }

    public static class LruCache {
        private static final boolean SORT_BY_ACCESS = true;
        private static final float LOAD_FACTOR = 0.75F;
        private final Map lruCacheMap;
        private final int capacity;

        public LruCache(int capacity) {
            this.capacity = capacity;
            this.lruCacheMap = new LinkedHashMap(capacity, LOAD_FACTOR, SORT_BY_ACCESS);
        }

        public V get(K key) {
            return lruCacheMap.get(key);
        }

        public void put(K key, V value) {
            if (lruCacheMap.containsKey(key)) {
                lruCacheMap.remove(key);
            } else if (lruCacheMap.size() >= capacity) {
                lruCacheMap.remove(lruCacheMap.keySet().iterator().next());
            }
            lruCacheMap.put(key, value);
        }
    }

    public static  LruCache createLruCache(final int capacity) {
        return new LruCache(capacity);
    }

    public static  List> createPermutationWithRepetition(final List list, final int permutationLength) {
        final long resultSize = (long) Math.pow(list.size(), permutationLength);
        final List> result = new ArrayList>((int) resultSize);
        final int[] bitVector = new int[permutationLength];
        for (int index = 0; index < resultSize; index += 1) {
            List result2 = new ArrayList(permutationLength);
            for (int index2 = 0; index2 < permutationLength; index2 += 1) {
                result2.add(list.get(bitVector[index2]));
            }
            int index3 = 0;
            while (index3 < permutationLength && bitVector[index3] == list.size() - 1) {
                bitVector[index3] = 0;
                index3 += 1;
            }
            if (index3 < permutationLength) {
                bitVector[index3] += 1;
            }
            result.add(result2);
        }
        return result;
    }

    public List> createPermutationWithRepetition(final int permutationLength) {
        return createPermutationWithRepetition((List) value(), permutationLength);
    }

    protected static  List newArrayList() {
        return com.github.underscore.U.newArrayList();
    }

    protected static  List newArrayList(final Iterable iterable) {
        return com.github.underscore.U.newArrayList(iterable);
    }

    protected static  Set newLinkedHashSet() {
        return com.github.underscore.U.newLinkedHashSet();
    }

    protected static  Map newLinkedHashMap() {
        return com.github.underscore.U.newLinkedHashMap();
    }

    public static String toJson(Collection collection) {
        return Json.toJson(collection);
    }

    public static String toJson(Map map) {
        return Json.toJson(map);
    }

    public String toJson() {
        return Json.toJson((Collection) getIterable());
    }

    public static String toJsonJavaString(Collection collection) {
        return Json.toJsonJavaString(collection);
    }

    public static String toJsonJavaString(Map map) {
        return Json.toJsonJavaString(map);
    }

    public String toJsonJavaString() {
        return Json.toJsonJavaString((Collection) getIterable());
    }

    @SuppressWarnings("unchecked")
    public static  T fromXml(final String xml) {
        return (T) Xml.fromXml(xml);
    }

    public static Map fromXmlMap(final String xml) {
        return fromXmlMap(xml, Xml.FromType.FOR_CONVERT);
    }

    @SuppressWarnings("unchecked")
    public static Map fromXmlMap(final String xml, final Xml.FromType fromType) {
        final Object object = Xml.fromXml(xml, fromType);
        final Map result;
        if (object instanceof Map) {
            result = (Map) object;
        } else {
            result = newLinkedHashMap();
            result.put("value", object);
        }
        return result;
    }

    @SuppressWarnings("unchecked")
    public static  T fromXml(final String xml, final Xml.FromType fromType) {
        return (T) Xml.fromXml(xml, fromType);
    }

    @SuppressWarnings("unchecked")
    public static  T fromXmlMakeArrays(final String xml) {
        return (T) Xml.fromXmlMakeArrays(xml);
    }

    @SuppressWarnings("unchecked")
    public static  T fromXmlWithoutNamespaces(final String xml) {
        return (T) Xml.fromXmlWithoutNamespaces(xml);
    }

    @SuppressWarnings("unchecked")
    public static  T fromXmlWithoutAttributes(final String xml) {
        return (T) Xml.fromXmlWithoutAttributes(xml);
    }

    @SuppressWarnings("unchecked")
    public static  T fromXmlWithoutNamespacesAndAttributes(final String xml) {
        return (T) Xml.fromXmlWithoutNamespacesAndAttributes(xml);
    }

    public static String toXml(Collection collection) {
        return Xml.toXml(collection);
    }

    public static String toXml(Map map) {
        return Xml.toXml(map);
    }

    @SuppressWarnings("unchecked")
    public static  T fromJson(String string) {
        return (T) Json.fromJson(string);
    }

    public Object fromJson() {
        return Json.fromJson(getString().get());
    }

    @SuppressWarnings("unchecked")
    public static Map fromJsonMap(final String string) {
        final Object object = Json.fromJson(string);
        final Map result;
        if (object instanceof Map) {
            result = (Map) object;
        } else {
            result = newLinkedHashMap();
            result.put("value", object);
        }
        return result;
    }

    public String toXml() {
        return Xml.toXml((Collection) getIterable());
    }

    public Object fromXml() {
        return Xml.fromXml(getString().get());
    }

    public static String jsonToXml(String json, Xml.XmlStringBuilder.Step identStep) {
        Object result = Json.fromJson(json);
        if (result instanceof Map) {
            return Xml.toXml((Map) result, identStep);
        }
        return Xml.toXml((List) result, identStep);
    }

    public static String jsonToXml(String json) {
        return jsonToXml(json, Xml.XmlStringBuilder.Step.TWO_SPACES);
    }

    @SuppressWarnings("unchecked")
    public static String xmlToJson(String xml, Json.JsonStringBuilder.Step identStep, Mode mode) {
        Object object = Xml.fromXml(xml);
        final String result;
        if (object instanceof Map) {
            if (mode == Mode.REPLACE_SELF_CLOSING_WITH_NULL) {
                result = Json.toJson(replaceSelfClosingWithNull((Map) object), identStep);
            } else if (mode == Mode.REPLACE_SELF_CLOSING_WITH_EMPTY) {
                result = Json.toJson(replaceSelfClosingWithEmpty((Map) object), identStep);
            } else {
                result = Json.toJson((Map) object, identStep);
            }
            return result;
        }
        return Json.toJson((List) object, identStep);
    }

    public static String xmlToJson(String xml) {
        return xmlToJson(xml, Json.JsonStringBuilder.Step.TWO_SPACES, null);
    }

    public static String xmlToJson(String xml, Mode mode) {
        return xmlToJson(xml, Json.JsonStringBuilder.Step.TWO_SPACES, mode);
    }

    public static String formatJson(String json, Json.JsonStringBuilder.Step identStep) {
        return Json.formatJson(json, identStep);
    }

    public static String formatJson(String json) {
        return Json.formatJson(json);
    }

    public static String formatXml(String xml, Xml.XmlStringBuilder.Step identStep) {
        return Xml.formatXml(xml, identStep);
    }

    public static String formatXml(String xml) {
        return Xml.formatXml(xml);
    }

    public static String changeXmlEncoding(String xml, Xml.XmlStringBuilder.Step identStep, String encoding) {
        return Xml.changeXmlEncoding(xml, identStep, encoding);
    }

    public static String changeXmlEncoding(String xml, String encoding) {
        return Xml.changeXmlEncoding(xml, encoding);
    }

    public static Map removeMinusesAndConvertNumbers(Map map) {
        Map outMap = newLinkedHashMap();
        for (Map.Entry entry : map.entrySet()) {
            final String newKey;
            if (entry.getKey().startsWith("-")) {
                newKey = entry.getKey().substring(1);
            } else {
                newKey = entry.getKey();
            }
            if (!entry.getKey().equals("-self-closing") && !entry.getKey().equals("#omit-xml-declaration")) {
                outMap.put(newKey, makeObject(entry.getValue()));
            }
        }
        return outMap;
    }

    @SuppressWarnings("unchecked")
    private static Object makeObject(Object value) {
        final Object result;
        if (value instanceof List) {
            List values = newArrayList();
            for (Object item : (List) value) {
                values.add(item instanceof Map ? removeMinusesAndConvertNumbers((Map) item) : item);
            }
            result = values;
        } else if (value instanceof Map) {
            result = removeMinusesAndConvertNumbers((Map) value);
        } else {
            String stringValue = String.valueOf(value);
            result = isJsonNumber(stringValue) ? Xml.stringToNumber(stringValue) : value;
        }
        return result;
    }

    public static boolean isJsonNumber(final String string) {
        boolean eFound = false;
        boolean periodValid = true;
        boolean pmValid = true;
        boolean numberEncountered = false;
        for (char ch : string.toCharArray()) {
            if (pmValid) {
                pmValid = false;
                if (ch == '-') {
                    continue;
                }
            }
            if (!eFound && (ch == 'e' || ch == 'E')) {
                eFound = true;
                periodValid = false;
                pmValid = true;
                numberEncountered = false;
                continue;
            }
            if (periodValid && ch == '.') {
                periodValid = false;
                continue;
            }
            if (ch < '0' || ch > '9') {
                return false;
            }
            numberEncountered = true;
        }
        return numberEncountered;
    }

    @SuppressWarnings("unchecked")
    public static Map replaceSelfClosingWithNull(Map map) {
        return (Map) replaceSelfClosingWithValue(map, null);
    }

    @SuppressWarnings("unchecked")
    public static Map replaceSelfClosingWithEmpty(Map map) {
        return (Map) replaceSelfClosingWithValue(map, "");
    }

    @SuppressWarnings("unchecked")
    public static Object replaceSelfClosingWithValue(Map map, String value) {
        Object outMap = newLinkedHashMap();
        for (Map.Entry entry : map.entrySet()) {
            if ("-self-closing".equals(entry.getKey()) && "true".equals(entry.getValue())) {
                if (map.size() == 1) {
                    outMap = value;
                    break;
                }
                continue;
            }
            ((Map) outMap).put(String.valueOf(entry.getKey()),
                makeObjectSelfClose(entry.getValue(), value));
        }
        return outMap;
    }

    @SuppressWarnings("unchecked")
    private static Object makeObjectSelfClose(Object value, String newValue) {
        final Object result;
        if (value instanceof List) {
            List values = newArrayList();
            for (Object item : (List) value) {
                values.add(item instanceof Map ? replaceSelfClosingWithValue((Map) item, newValue) : item);
            }
            result = values;
        } else if (value instanceof Map) {
            result = replaceSelfClosingWithValue((Map) value, newValue);
        } else {
            result = value;
        }
        return result;
    }

    public static long gcd(long value1, long value2) {
        if (value1 == 0) {
            return value2;
        }
        return gcd(value2 % value1, value1);
    }

    public static long findGcd(long ... array) {
        long result = array[0];
        for (int index = 1; index < array.length; index += 1) {
            result = gcd(array[index], result);
        }
        return result;
    }

    public static Builder objectBuilder() {
        return new U.Builder();
    }

    public static class Builder {
        private final Map data;
        public Builder() {
            data = newLinkedHashMap();
        }

        public Builder add(final String key, final Object value) {
            data.put(key, value);
            return this;
        }

        public Builder add(final Object value) {
            data.put(String.valueOf(data.size()), value);
            return this;
        }

        public Builder set(final String path, final Object value) {
            U.set(data, path, value);
            return this;
        }

        public Builder add(final Builder builder) {
            data.put(String.valueOf(data.size()), builder.build());
            return this;
        }

        public Builder add(final String key, final ArrayBuilder builder) {
            data.put(key, builder.build());
            return this;
        }

        public Builder add(final String key, final Builder builder) {
            data.put(key, builder.build());
            return this;
        }

        @SuppressWarnings("unchecked")
        public Map build() {
            return (Map) ((LinkedHashMap) data).clone();
        }

        public String toXml() {
            return Xml.toXml(data);
        }

        public static Builder fromXml(final String xml) {
            final Builder builder = new Builder();
            builder.data.putAll(fromXmlMap(xml));
            return builder;
        }

        public String toJson() {
            return Json.toJson(data);
        }

        public static Builder fromJson(final String json) {
            final Builder builder = new Builder();
            builder.data.putAll(fromJsonMap(json));
            return builder;
        }

        @Override
        public String toString() {
            return data.toString();
        }
    }

    public static ArrayBuilder arrayBuilder() {
        return new U.ArrayBuilder();
    }

    public static class ArrayBuilder {
        private final List data;
        public ArrayBuilder() {
            data = newArrayList();
        }

        public ArrayBuilder add(final Object value) {
            data.add(value);
            return this;
        }

        public ArrayBuilder set(final int index, final Object value) {
            data.set(index, value);
            return this;
        }

        public ArrayBuilder add(final ArrayBuilder builder) {
            data.addAll(builder.build());
            return this;
        }

        public ArrayBuilder add(final Builder builder) {
            data.add(builder.build());
            return this;
        }

        @SuppressWarnings("unchecked")
        public List build() {
            return (List) ((ArrayList) data).clone();
        }

        public String toXml() {
            return Xml.toXml(data);
        }

        public static ArrayBuilder fromXml(final String xml) {
            final ArrayBuilder builder = new ArrayBuilder();
            builder.data.addAll(U.>fromXml(xml));
            return builder;
        }

        public String toJson() {
            return Json.toJson(data);
        }

        public static ArrayBuilder fromJson(final String json) {
            final ArrayBuilder builder = new ArrayBuilder();
            builder.data.addAll(U.>fromJson(json));
            return builder;
        }

        @Override
        public String toString() {
            return data.toString();
        }
    }
}