/*
 *  Copyright 2014 Alexey Andreev.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.teavm.classlib.java.util;

import org.teavm.classlib.java.lang.TObject;

public final class TObjects extends TObject {
    public static boolean equals(Object a, Object b) {
        if (a == b) {
            return true;
        }
        return a == null ? b == null : a.equals(b);
    }

    public static int hashCode(Object o) {
        return o == null ? 0 : o.hashCode();
    }

    public static String toString(Object o) {
        return toString(o, "null");
    }

    public static String toString(Object o, String nullDefault) {
        return o != null ? o.toString() : nullDefault;
    }

    public static <T> int compare(T a, T b, TComparator<? super T> c) {
        return a == null && b == null ? 0 : c.compare(a, b);
    }

    public static <T> T requireNonNull(T obj) {
        return requireNonNull(obj, "");
    }

    public static <T> T requireNonNull(T obj, String message) {
        if (obj == null) {
            throw new NullPointerException(message);
        }
        return obj;
    }

    public static boolean nonNull(Object obj) {
        return obj != null;
    }

    public static boolean deepEquals(Object a, Object b) {
        if (a == b) {
            return true;
        }
        if (a == null) {
            return b == null;
        }
        if (a instanceof boolean[]) {
            return b instanceof boolean[] && TArrays.equals((boolean[]) a, (boolean[]) b);
        } else if (b instanceof boolean[]) {
            return false;
        } else if (a instanceof byte[]) {
            return b instanceof byte[] && TArrays.equals((byte[]) a, (byte[]) b);
        } else if (b instanceof byte[]) {
            return false;
        } else if (a instanceof short[]) {
            return b instanceof short[] && TArrays.equals((short[]) a, (short[]) b);
        } else if (b instanceof short[]) {
            return false;
        } else if (a instanceof int[]) {
            return b instanceof int[] && TArrays.equals((int[]) a, (int[]) b);
        } else if (b instanceof int[]) {
            return false;
        } else if (a instanceof char[]) {
            return b instanceof char[] && TArrays.equals((char[]) a, (char[]) b);
        } else if (b instanceof char[]) {
            return false;
        } else if (a instanceof float[]) {
            return b instanceof float[] && TArrays.equals((float[]) a, (float[]) b);
        } else if (b instanceof float[]) {
            return false;
        } else if (a instanceof double[]) {
            return b instanceof double[] && TArrays.equals((double[]) a, (double[]) b);
        } else if (b instanceof double[]) {
            return false;
        } else if (a instanceof Object[]) {
            return b instanceof Object[] && TArrays.deepEquals((Object[]) a, (Object[]) b);
        } else if (b instanceof Object[]) {
            return false;
        } else {
            return a.equals(b);
        }
    }

    public static int hash(Object... values) {
        return TArrays.hashCode(values);
    }
}

@@ -642,16 +642,52 @@
 .util;%0A%0A
+import java.util.function.Supplier;%0A
 import o
@@ -723,16 +723,16 @@
 Object;%0A
-
 %0Apublic 
@@ -1661,32 +1661,624 @@
 urn obj;%0A    %7D%0A%0A
+    public static %3CT%3E T requireNonNull(T obj, Supplier%3CString%3E messageSupplier) %7B%0A        if (obj == null) %7B%0A            throw new NullPointerException(messageSupplier.get());%0A        %7D%0A        return obj;%0A    %7D%0A%0A    public static %3CT%3E T requireNonNullElse(T obj, T defaultObj) %7B%0A        return obj != null ? obj : requireNonNull(defaultObj);%0A    %7D%0A%0A    public static %3CT%3E T requireNonNullElseGet(T obj, Supplier%3C? extends T%3E supplier) %7B%0A        return obj != null ? obj : requireNonNull(supplier.get());%0A    %7D%0A%0A    public static boolean isNull(Object obj) %7B%0A        return obj == null;%0A    %7D%0A%0A
     public stati
@@ -4207,24 +4207,24 @@
 . values) %7B%0A
-
         retu
@@ -4257,11 +4257,694 @@
 );%0A    %7D
+%0A%0A    public static int checkIndex(int index, int length) %7B%0A        if (index %3C 0 %7C%7C index %3E= length) %7B%0A            throw new IndexOutOfBoundsException();%0A        %7D%0A        return index;%0A    %7D%0A%0A    public static int checkFromToIndex(int fromIndex, int toIndex, int length) %7B%0A        if (fromIndex %3C 0 %7C%7C fromIndex %3E toIndex %7C%7C toIndex %3E length) %7B%0A            throw new IndexOutOfBoundsException();%0A        %7D%0A        return fromIndex;%0A    %7D%0A%0A    public static int checkFromIndexSize(int fromIndex, int size, int length) %7B%0A        if (fromIndex %3C 0 %7C%7C size %3C 0 %7C%7C fromIndex + size %3E length) %7B%0A            throw new IndexOutOfBoundsException();%0A        %7D%0A        return fromIndex;%0A    %7D
 %0A%7D%0A

add methods to java.util.Objects