Fs.java

package space.sunqian.fs;

import space.sunqian.annotation.Immutable;
import space.sunqian.annotation.Nonnull;
import space.sunqian.annotation.Nullable;
import space.sunqian.annotation.RetainedParam;
import space.sunqian.fs.base.exception.AwaitingException;
import space.sunqian.fs.base.function.BooleanCallable;
import space.sunqian.fs.base.function.VoidCallable;
import space.sunqian.fs.base.option.Option;
import space.sunqian.fs.base.process.ProcessKit;
import space.sunqian.fs.base.string.StringKit;
import space.sunqian.fs.base.thread.ThreadKit;
import space.sunqian.fs.base.value.Ret;
import space.sunqian.fs.collect.ArrayKit;
import space.sunqian.fs.collect.ListKit;
import space.sunqian.fs.collect.MapKit;
import space.sunqian.fs.collect.SetKit;
import space.sunqian.fs.collect.StreamKit;
import space.sunqian.fs.io.IORuntimeException;
import space.sunqian.fs.object.ObjectKit;
import space.sunqian.fs.object.convert.ConvertOption;
import space.sunqian.fs.object.convert.DataMapper;
import space.sunqian.fs.object.convert.ObjectConvertException;
import space.sunqian.fs.object.convert.ObjectConverter;
import space.sunqian.fs.object.convert.UnsupportedObjectConvertException;
import space.sunqian.fs.object.data.ObjectSchema;
import space.sunqian.fs.reflect.TypeRef;

import java.lang.reflect.Type;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.RandomAccess;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Stream;

/**
 * The core utility class of this library, provides support methods for {@link Object}, such as {@code equals} and
 * {@code hashCode}. And many methods to improve language convenience, such as {@code nonnull}, {@code uncheck}. And
 * shortcuts to other commonly used methods in this lib, such as {@link #list(Object[])},
 * {@link #copyProperties(Object, Object, Option[])}, {@link #convert(Object, Class, Option[])}, etc.
 *
 * @author sunqian
 */
public class Fs {

    /**
     * Name of this lib.
     */
    public static final @Nonnull String LIB_NAME = "fs";

    /**
     * Version of this lib.
     */
    public static final @Nonnull String LIB_VERSION = "0.0.1-SNAPSHOT";

    /**
     * String value for {@code null}.
     */
    public static final @Nonnull String NULL_STRING = Objects.toString(null);

    /**
     * Casts and returns the given object as the specified type {@code T}. This method is equivalent to:
     * <pre>{@code
     * return (T) obj;
     * }</pre>
     *
     * @param obj the given object
     * @param <T> the specified type
     * @return the given object as the specified type {@code T}
     */
    @SuppressWarnings("noinspection unchecked")
    public static <T> T as(@Nullable Object obj) {
        return (T) obj;
    }

    /**
     * Directly returns the given object itself. The given object is annotated by {@link Nullable}, but the return value
     * is annotated by {@link Nonnull}. This method is used to suppress some IDE or compilation warnings.
     *
     * @param obj the given object
     * @param <T> the type of the given object
     * @return the given object itself
     */
    @SuppressWarnings("ConstantConditions")
    public static <T> @Nonnull T asNonnull(@Nullable T obj) {
        return obj;
    }

    /**
     * Returns the default value if the given object is {@code null}, or the given object itself if it is not
     * {@code null}. This method is equivalent to:
     * <pre>{@code
     * return obj == null ? defaultValue : obj;
     * }</pre>
     * <p>
     * Note this method does not guarantee that the returned value must be {@code nonnull}.
     *
     * @param obj          the given object
     * @param defaultValue the default value
     * @param <T>          the type of the returned value
     * @return the default value if the given object is {@code null}, or the given object itself if it is not
     * {@code null}
     */
    public static <T> T nonnull(@Nullable T obj, T defaultValue) {
        return obj == null ? defaultValue : obj;
    }

    /**
     * Returns the value computed from the specified supplier if the given object is {@code null}, or the given object
     * itself if it is not {@code null}. This method is equivalent to:
     * <pre>{@code
     * return obj == null ? supplier.get() : obj;
     * }</pre>
     * <p>
     * Note this method does not guarantee that the returned value must be {@code nonnull}.
     *
     * @param obj      the given object
     * @param supplier the specified supplier
     * @param <T>      the type of the returned value
     * @return the value computed from the specified supplier if the given object is {@code null}, or the given object
     * itself if it is not {@code null}
     */
    public static <T> T nonnull(@Nullable T obj, Supplier<? extends T> supplier) {
        return obj == null ? supplier.get() : obj;
    }

    /**
     * Runs the given action and wraps any exception into an unchecked exception, the unchecked exception is generated
     * by the given unchecked exception generator. The logic as follows:
     * <pre>{@code
     * try {
     *     action.call();
     * } catch (Exception e) {
     *     throw unchecked.apply(e);
     * }
     * }</pre>
     *
     * @param action    the given action
     * @param unchecked the given unchecked exception generator
     */
    public static void uncheck(
        @Nonnull VoidCallable action,
        @Nonnull Function<? super @Nonnull Exception, ? extends @Nonnull RuntimeException> unchecked
    ) {
        try {
            action.call();
        } catch (Exception e) {
            throw unchecked.apply(e);
        }
    }

    /**
     * Runs the given action and wraps any exception into an unchecked exception, the unchecked exception is generated
     * by the given unchecked exception generator. The logic as follows:
     * <pre>{@code
     * try {
     *     return action.call();
     * } catch (Exception e) {
     *     throw unchecked.apply(e);
     * }
     * }</pre>
     *
     * @param action    the given action
     * @param unchecked the given unchecked exception generator
     * @param <T>       the type of the result
     * @return the result of the given action
     */
    public static <T> T uncheck(
        @Nonnull Callable<T> action,
        @Nonnull Function<? super @Nonnull Exception, ? extends @Nonnull RuntimeException> unchecked
    ) {
        try {
            return action.call();
        } catch (Exception e) {
            throw unchecked.apply(e);
        }
    }

    /**
     * Runs the given action and ignores any exception thrown by the action. The logic as follows:
     * <pre>{@code
     * try {
     *     action.call();
     * } catch (Exception ignored) {
     * }
     * }</pre>
     *
     * @param action the given action
     */
    public static void uncheck(@Nonnull VoidCallable action) {
        try {
            action.call();
        } catch (Exception ignored) {
        }
    }

    /**
     * Calls the given action and returns the result. If any exception is thrown, returns the default value. The logic
     * as follows:
     * <pre>{@code
     * try {
     *     return action.call();
     * } catch (Exception e) {
     *     return defaultValue;
     * }
     * }</pre>
     *
     * @param action       the given action
     * @param defaultValue the default value
     * @param <T>          the type of the result
     * @return the result of the given action, or the default value if any exception is thrown
     */
    public static <T> T call(@Nonnull Callable<T> action, T defaultValue) {
        try {
            return action.call();
        } catch (Exception e) {
            return defaultValue;
        }
    }

    /**
     * Calls the given action and returns the result wrapped by {@link Ret}. The logic as follows:
     * <pre>{@code
     * try {
     *     T ret = action.call();
     *     return Ret.of(ret);
     * } catch (Throwable e) {
     *     return Ret.of(e);
     * }
     * }</pre>
     *
     * @param action the given action
     * @param <T>    the type of the result
     * @return the result of the given action wrapped by {@link Ret}
     */
    public static <T> Ret<T> call(@Nonnull Callable<T> action) {
        try {
            T ret = action.call();
            return Ret.of(ret);
        } catch (Throwable e) {
            return Ret.of(e);
        }
    }

    /**
     * Executes the given task until it returns {@code true} or throws an exception. The original exception will be
     * wrapped by {@link AwaitingException} then thrown, using {@link AwaitingException#getCause()} can get the original
     * exception. The logic of this method is as follows:
     * <pre>{@code
     * try {
     *     while (true) {
     *         if (task.call()) {
     *             return;
     *         }
     *     }
     * } catch (Exception e) {
     *     throw new AwaitingException(e);
     * }
     * }</pre>
     * <p>
     * Note this method may cause high CPU usage. When the task determines to return {@code false}, consider adding some
     * measures (such as sleep the current thread in a very short time) to avoid it.
     *
     * @param task the given task to be executed
     * @throws AwaitingException if an error occurs while awaiting
     */
    public static void until(@Nonnull BooleanCallable task) throws AwaitingException {
        try {
            while (true) {
                if (task.call()) {
                    return;
                }
            }
        } catch (Exception e) {
            throw new AwaitingException(e);
        }
    }

    //---------------- Equals Begin ----------------//

    /**
     * Returns whether the given objects are equal. If the given objects are arrays, uses {@code Arrays.equals} or
     * {@link Arrays#deepEquals(Object[], Object[])} if necessary.
     * <p>
     * This method is equivalent to ({@link #equalsWith(Object, Object, boolean, boolean)}):
     * {@code equalsWith(a, b, true, true)}.
     * <p>
     * This method is a shortcut to the {@link ObjectKit#equals(Object, Object)}.
     *
     * @param a the given object a
     * @param b the given object b
     * @return whether the given objects are equal
     */
    public static boolean equals(@Nullable Object a, @Nullable Object b) {
        return ObjectKit.equals(a, b);
    }

    /**
     * Returns whether the given objects are equal each other by {@link #equals(Object, Object)}.
     * <p>
     * This method is a shortcut to the {@link ObjectKit#equalsAll(Object[])}.
     *
     * @param objects the given objects
     * @return whether the given objects are equal
     */
    public static boolean equalsAll(@Nullable Object @Nonnull ... objects) {
        return ObjectKit.equalsAll(objects);
    }

    /**
     * Returns whether the given objects are equal. This method follows the following logic:
     * <ul>
     *     <li>
     *         If {@code a == b}, returns {@code true};
     *     </li>
     *     <li>
     *         If the {@code arrayEquals} is {@code true}:
     *         <ul>
     *             <li>
     *                 If the {@code deep} is {@code true}, uses {@link Arrays#deepEquals(Object[], Object[])} for
     *                 them. Otherwise, uses {@code Arrays.equals}.
     *             </li>
     *         </ul>
     *     </li>
     *     <li>
     *         Returns {@link Objects#equals(Object, Object)} otherwise.
     *     </li>
     * </ul>
     * <p>
     * This method is a shortcut to the {@link ObjectKit#equalsWith(Object, Object, boolean, boolean)}.
     *
     * @param a           the given object a
     * @param b           the given object b
     * @param arrayEquals the arrayEquals option
     * @param deep        the deep option
     * @return whether the given objects are equal
     */
    public static boolean equalsWith(@Nullable Object a, @Nullable Object b, boolean arrayEquals, boolean deep) {
        return ObjectKit.equalsWith(a, b, arrayEquals, deep);
    }

    //---------------- Equals End ----------------//

    //---------------- Hashcode Begin ----------------//

    /**
     * Returns the hashcode of the given object. If the given object is array, uses {@code Arrays.hashCode} or
     * {@link Arrays#deepHashCode(Object[])} if necessary.
     * <p>
     * This method is equivalent to ({@link #hashWith(Object, boolean, boolean)}): {@code hashWith(obj, true, true)}.
     * <p>
     * This method is a shortcut to the {@link ObjectKit#hashCode(Object)}.
     *
     * @param obj the given object
     * @return the hashcode of the given object
     */
    public static int hashCode(@Nullable Object obj) {
        return ObjectKit.hashCode(obj);
    }

    /**
     * Returns the hashcode of the given objects via {@link Arrays#deepHashCode(Object[])}.
     * <p>
     * This method is a shortcut to the {@link ObjectKit#hashAll(Object[])}.
     *
     * @param objs the given objects
     * @return the hashcode of the given objects via {@link Arrays#deepHashCode(Object[])}
     */
    public static int hashAll(@Nullable Object @Nonnull ... objs) {
        return ObjectKit.hashAll(objs);
    }

    /**
     * Returns the hashcode of the given object. This method follows the following logic:
     * <ul>
     *     <li>
     *         If the given object is not an array, returns {@link Objects#hashCode(Object)}.
     *     </li>
     *     <li>
     *         If the {@code arrayHash} is {@code true}:
     *         <ul>
     *             <li>
     *                 If the {@code deep} is {@code true}, uses {@link Arrays#deepHashCode(Object[])} for them.
     *                 Otherwise, uses {@code Arrays.hashCode}.
     *             </li>
     *         </ul>
     *     </li>
     *     <li>
     *         Returns {@link Objects#hashCode(Object)} otherwise.
     *     </li>
     * </ul>
     * <p>
     * This method is a shortcut to the {@link ObjectKit#hashWith(Object, boolean, boolean)}.
     *
     * @param obj       the given object
     * @param arrayHash the arrayHash option
     * @param deep      the deep option
     * @return the hashcode of the given object
     */
    public static int hashWith(@Nullable Object obj, boolean arrayHash, boolean deep) {
        return ObjectKit.hashWith(obj, arrayHash, deep);
    }

    /**
     * Returns the identity hashcode of the given object, this method is equivalent to
     * {@link System#identityHashCode(Object)}.
     * <p>
     * This method is a shortcut to the {@link ObjectKit#id(Object)}.
     *
     * @param obj the given object
     * @return the identity hashcode of the given object
     */
    public static int id(@Nullable Object obj) {
        return ObjectKit.id(obj);
    }

    //---------------- Hashcode End ----------------//

    //---------------- ToString Begin ----------------//

    /**
     * Returns the {@code toString} of the given object. If the given object is array, uses {@code Arrays.toString} or
     * {@link Arrays#deepToString(Object[])} if necessary.
     * <p>
     * This method is equivalent to ({@link #toStringWith(Object, boolean, boolean)}):
     * {@code toStringWith(obj, true, true)}.
     * <p>
     * This method is a shortcut to the {@link StringKit#toString(Object)}.
     *
     * @param obj the given object
     * @return the {@code toString} of the given object
     */
    public static @Nonnull String toString(@Nullable Object obj) {
        return StringKit.toString(obj);
    }

    /**
     * Returns the {@code toString} of the given objects via {@link Arrays#deepToString(Object[])}.
     * <p>
     * This method is a shortcut to the {@link StringKit#toStringAll(Object[])}.
     *
     * @param objs the given objects
     * @return the {@code toString} of the given objects via {@link Arrays#deepToString(Object[])}
     */
    public static @Nonnull String toStringAll(@Nullable Object @Nonnull ... objs) {
        return StringKit.toStringAll(objs);
    }

    /**
     * Returns the {@code toString} of the given object. This method follows the following logic:
     * <ul>
     *     <li>
     *         If the given object is not an array, returns {@link Objects#toString(Object)}.
     *     </li>
     *     <li>
     *         If the {@code arrayToString} is {@code true}:
     *         <ul>
     *             <li>
     *                 If the {@code deep} is {@code true}, uses {@link Arrays#deepToString(Object[])} for them.
     *                 Otherwise, uses {@code Arrays.toString}.
     *             </li>
     *         </ul>
     *     </li>
     *     <li>
     *         Returns {@link Objects#toString(Object)} otherwise.
     *     </li>
     * </ul>
     * <p>
     * This method is a shortcut to the {@link StringKit#toStringWith(Object, boolean, boolean)}.
     *
     * @param obj           the given object
     * @param arrayToString the arrayToString option
     * @param deep          the deep option
     * @return the {@code toString} of the given object
     */
    public static @Nonnull String toStringWith(@Nullable Object obj, boolean arrayToString, boolean deep) {
        return StringKit.toStringWith(obj, arrayToString, deep);
    }

    //---------------- ToString End ----------------//

    //---------------- Copy Properties Begin ----------------//

    /**
     * Copy properties from the given source object to the given destination object. The object can be a {@link Map} or
     * a non-map object which can be parsed to {@link ObjectSchema}.
     * <p>
     * The options parameter can be empty, in which case the default behavior will be used, or built-in options in
     * {@link ConvertOption} or other custom options for custom implementations.
     * <p>
     * This method is a shortcut to the {@link DataMapper#copyProperties(Object, Object, Option[])}.
     *
     * @param src     the given source object
     * @param dst     the given destination object
     * @param options the options for copying properties
     * @throws ObjectConvertException if an error occurs during copying properties
     * @see DataMapper
     */
    public static void copyProperties(
        @Nonnull Object src, @Nonnull Object dst, @Nonnull Option<?, ?> @Nonnull ... options
    ) throws ObjectConvertException {
        DataMapper.defaultMapper().copyProperties(src, dst, options);
    }

    /**
     * Copy properties from the given source object to the given destination object. The object can be a {@link Map} or
     * a non-map object which can be parsed to {@link ObjectSchema}.
     * <p>
     * The options parameter can be empty, in which case the default behavior will be used, or built-in options in
     * {@link ConvertOption} or other custom options for custom implementations.
     * <p>
     * This method is a shortcut to the {@link DataMapper#copyProperties(Object, Object, ObjectConverter, Option[])}.
     *
     * @param src       the given source object
     * @param dst       the given destination object
     * @param converter the converter for converting values of the properties if needed
     * @param options   the options for copying properties
     * @throws ObjectConvertException if an error occurs during copying properties
     * @see DataMapper
     */
    public static void copyProperties(
        @Nonnull Object src,
        @Nonnull Object dst,
        @Nonnull ObjectConverter converter,
        @Nonnull Option<?, ?> @Nonnull ... options
    ) throws ObjectConvertException {
        DataMapper.defaultMapper().copyProperties(src, dst, converter, options);
    }

    /**
     * Copy properties from the given source object to the given destination object. The object can be a {@link Map} or
     * a non-map object which can be parsed to {@link ObjectSchema}.
     * <p>
     * The options parameter can be empty, in which case the default behavior will be used, or built-in options in
     * {@link ConvertOption} or other custom options for custom implementations.
     * <p>
     * This method is a shortcut to the {@link DataMapper#copyProperties(Object, Type, Object, Type, Option[])}.
     *
     * @param src     the given source object
     * @param srcType specifies the type of the given source object
     * @param dst     the given destination object
     * @param dstType specifies the type of the given destination object
     * @param options the options for copying properties
     * @throws ObjectConvertException if an error occurs during copying properties
     * @see DataMapper
     */
    public static void copyProperties(
        @Nonnull Object src,
        @Nonnull Type srcType,
        @Nonnull Object dst,
        @Nonnull Type dstType,
        @Nonnull Option<?, ?> @Nonnull ... options
    ) throws ObjectConvertException {
        DataMapper.defaultMapper().copyProperties(
            src,
            srcType,
            dst,
            dstType,
            options
        );
    }

    /**
     * Copy properties from the given source object to the given destination object. The object can be a {@link Map} or
     * a non-map object which can be parsed to {@link ObjectSchema}.
     * <p>
     * The options parameter can be empty, in which case the default behavior will be used, or built-in options in
     * {@link ConvertOption} or other custom options for custom implementations.
     * <p>
     * This method is a shortcut to the
     * {@link DataMapper#copyProperties(Object, Type, Object, Type, ObjectConverter, Option[])}.
     *
     * @param src       the given source object
     * @param srcType   specifies the type of the given source object
     * @param dst       the given destination object
     * @param dstType   specifies the type of the given destination object
     * @param converter the converter for converting values of the properties if needed
     * @param options   the options for copying properties
     * @throws ObjectConvertException if an error occurs during copying properties
     * @see DataMapper
     */
    public static void copyProperties(
        @Nonnull Object src,
        @Nonnull Type srcType,
        @Nonnull Object dst,
        @Nonnull Type dstType,
        @Nonnull ObjectConverter converter,
        @Nonnull Option<?, ?> @Nonnull ... options
    ) throws ObjectConvertException {
        DataMapper.defaultMapper().copyProperties(
            src,
            srcType,
            dst,
            dstType,
            converter,
            options
        );
    }

    //---------------- Copy Properties End ----------------//

    //---------------- Object Conversion Begin ----------------//

    /**
     * Converts the given source object from the specified type to the target type.
     * <p>
     * The options parameter can be empty, in which case the default behavior will be used, or built-in options in
     * {@link ConvertOption} or other custom options for custom implementations.
     * <p>
     * This method is a shortcut to the {@link ObjectConverter#convert(Object, Class, Option[])}.
     *
     * @param src     the given source object
     * @param target  the specified type of the target object
     * @param options the other conversion options
     * @param <T>     the target type
     * @return the converted object, {@code null} is permitted
     * @throws UnsupportedObjectConvertException if the conversion from the specified type to the target type is not
     *                                           supported
     * @throws ObjectConvertException            if the conversion failed
     * @see ObjectConverter
     */
    public static <T> T convert(
        @Nullable Object src,
        @Nonnull Class<? extends T> target,
        @Nonnull Option<?, ?> @Nonnull ... options
    ) throws UnsupportedObjectConvertException, ObjectConvertException {
        return ObjectConverter.defaultConverter().convert(src, target, options);
    }

    /**
     * Converts the given source object from the specified type to the target type.
     * <p>
     * The options parameter can be empty, in which case the default behavior will be used, or built-in options in
     * {@link ConvertOption} or other custom options for custom implementations.
     * <p>
     * This method is a shortcut to the {@link ObjectConverter#convert(Object, TypeRef, Option[])}.
     *
     * @param src     the given source object
     * @param target  the specified type ref of the target object
     * @param options the other conversion options
     * @param <T>     the target type
     * @return the converted object, {@code null} is permitted
     * @throws UnsupportedObjectConvertException if the conversion from the specified type to the target type is not
     *                                           supported
     * @throws ObjectConvertException            if the conversion failed
     * @see ObjectConverter
     */
    public static <T> T convert(
        @Nullable Object src,
        @Nonnull TypeRef<? extends T> target,
        @Nonnull Option<?, ?> @Nonnull ... options
    ) throws UnsupportedObjectConvertException, ObjectConvertException {
        return ObjectConverter.defaultConverter().convert(src, target, options);
    }

    /**
     * Converts the given source object from the specified type to the target type.
     * <p>
     * The options parameter can be empty, in which case the default behavior will be used, or built-in options in
     * {@link ConvertOption} or other custom options for custom implementations.
     * <p>
     * This method is a shortcut to the {@link ObjectConverter#convert(Object, Type, Class, Option[])}.
     *
     * @param src     the given source object
     * @param srcType the specified type of the given source object
     * @param target  the specified type of the target object
     * @param options the other conversion options
     * @param <T>     the target type
     * @return the converted object, {@code null} is permitted
     * @throws UnsupportedObjectConvertException if the conversion from the specified type to the target type is not
     *                                           supported
     * @throws ObjectConvertException            if the conversion failed
     * @see ObjectConverter
     */
    public static <T> T convert(
        @Nullable Object src,
        @Nonnull Type srcType,
        @Nonnull Class<? extends T> target,
        @Nonnull Option<?, ?> @Nonnull ... options
    ) throws UnsupportedObjectConvertException, ObjectConvertException {
        return ObjectConverter.defaultConverter().convert(src, srcType, target, options);
    }

    /**
     * Converts the given source object from the specified type to the target type.
     * <p>
     * The options parameter can be empty, in which case the default behavior will be used, or built-in options in
     * {@link ConvertOption} or other custom options for custom implementations.
     * <p>
     * This method is a shortcut to the {@link ObjectConverter#convert(Object, Type, TypeRef, Option[])}.
     *
     * @param src     the given source object
     * @param srcType the specified type of the given source object
     * @param target  the specified type ref of the target object
     * @param options the other conversion options
     * @param <T>     the target type
     * @return the converted object, {@code null} is permitted
     * @throws UnsupportedObjectConvertException if the conversion from the specified type to the target type is not
     *                                           supported
     * @throws ObjectConvertException            if the conversion failed
     * @see ObjectConverter
     */
    public static <T> T convert(
        @Nullable Object src,
        @Nonnull Type srcType,
        @Nonnull TypeRef<? extends T> target,
        @Nonnull Option<?, ?> @Nonnull ... options
    ) throws UnsupportedObjectConvertException, ObjectConvertException {
        return ObjectConverter.defaultConverter().convert(src, srcType, target, options);
    }

    //---------------- Object Conversion End ----------------//

    //---------------- Collection Begin ----------------//

    /**
     * Directly returns the given variable arguments as an array.
     * <p>
     * This method is a shortcut to the {@link ArrayKit#array(Object[])}.
     *
     * @param elements the given variable arguments
     * @param <T>      the component type
     * @return the given variable arguments as an array
     * @see ArrayKit
     */
    @SafeVarargs
    public static <T> T @Nonnull [] array(T @Nonnull @RetainedParam ... elements) {
        return ArrayKit.array(elements);
    }

    /**
     * Returns an immutable list backed by the given array. The returned list is immutable but the backing array is not,
     * changes to the backing array "write through" to the returned list. The returned list is serializable and
     * implements {@link RandomAccess}.
     * <p>
     * This method is a shortcut to the {@link ListKit#list(Object[])}.
     *
     * @param array the given array
     * @param <T>   the component type
     * @return an immutable list backed by the given array
     * @see ListKit
     */
    @SafeVarargs
    public static <T> @Nonnull @Immutable List<T> list(T @Nonnull @RetainedParam ... array) {
        return ListKit.list(array);
    }

    /**
     * Returns a new {@link ArrayList} initialing with the given array.
     * <p>
     * This method is a shortcut to the {@link ListKit#arrayList(Object[])}.
     *
     * @param array the given array
     * @param <T>   the component type
     * @return a new {@link ArrayList} initialing with the given array
     * @see ListKit
     */
    @SafeVarargs
    public static <T> @Nonnull ArrayList<T> arrayList(T @Nonnull ... array) {
        return ListKit.arrayList(array);
    }

    /**
     * Returns a new {@link LinkedList} initialing with the given array.
     * <p>
     * This method is a shortcut to the {@link ListKit#linkedList(Object[])}.
     *
     * @param array the given array
     * @param <T>   the component type
     * @return a new {@link LinkedList} initialing with the given array
     * @see ListKit
     */
    @SafeVarargs
    public static <T> @Nonnull LinkedList<T> linkedList(T @Nonnull ... array) {
        return ListKit.linkedList(array);
    }

    /**
     * Returns a new immutable set of which content is added from the given array. The content of the set is added in
     * array order, and the duplicate elements will be ignored. The behavior of this method is equivalent to:
     * <pre>{@code
     * return Collections.unmodifiableSet(linkedHashSet(array));
     * }</pre>
     * <p>
     * This method is a shortcut to the {@link SetKit#set(Object[])}.
     *
     * @param array the given array
     * @param <T>   the component type
     * @return a new immutable set of which content is added from the given array
     * @see SetKit
     */
    @SafeVarargs
    public static <T> @Nonnull @Immutable Set<T> set(T @Nonnull ... array) {
        return SetKit.set(array);
    }

    /**
     * Returns a new {@link HashSet} initialing with the given array.
     * <p>
     * This method is a shortcut to the {@link SetKit#hashSet(Object[])}.
     *
     * @param array the given array
     * @param <T>   the component type
     * @return a new {@link HashSet} initialing with the given array
     * @see SetKit
     */
    @SafeVarargs
    public static <T> @Nonnull HashSet<T> hashSet(T @Nonnull ... array) {
        return SetKit.hashSet(array);
    }

    /**
     * Returns a new {@link LinkedHashSet} initialing with the given array.
     * <p>
     * This method is a shortcut to the {@link SetKit#linkedHashSet(Object[])}.
     *
     * @param array the given array
     * @param <T>   the component type
     * @return a new {@link LinkedHashSet} initialing with the given array
     * @see SetKit
     */
    @SafeVarargs
    public static <T> @Nonnull LinkedHashSet<T> linkedHashSet(T @Nonnull ... array) {
        return SetKit.linkedHashSet(array);
    }

    /**
     * Returns a new immutable map of which content is added from the given array.
     * <p>
     * Every two elements of the array form a key-value pair, that means, the {@code array[0]} and {@code array[1]} will
     * be the first key-value pair, the {@code array[2]} and {@code array[3]} will be the second key-value pair, and so
     * on. If the length of the array is odd and the last key cannot match the value, then the last pair will be the
     * key-{@code null} pair to put.
     * <p>
     * The behavior of this method is equivalent to:
     * <pre>{@code
     *  return Collections.unmodifiableMap(linkedHashMap(array));
     *  }</pre>
     * <p>
     * This method is a shortcut to the {@link MapKit#map(Object[])}.
     *
     * @param array the given array
     * @param <K>   the key type
     * @param <V>   the value type
     * @return a new {@link HashMap} initialing with the given array
     * @see MapKit
     */
    public static <K, V> @Nonnull @Immutable Map<K, V> map(Object @Nonnull ... array) {
        return MapKit.map(array);
    }

    /**
     * Returns a new {@link HashMap} initialing with the given array.
     * <p>
     * Every two elements of the array form a key-value pair, that means, the {@code array[0]} and {@code array[1]} will
     * be the first key-value pair, the {@code array[2]} and {@code array[3]} will be the second key-value pair, and so
     * on. If the length of the array is odd and the last key cannot match the value, then the last pair will be the
     * key-{@code null} pair to put.
     * <p>
     * This method is a shortcut to the {@link MapKit#hashMap(Object[])}.
     *
     * @param array the given array
     * @param <K>   the key type
     * @param <V>   the value type
     * @return a new {@link HashMap} initialing with the given array
     * @see MapKit
     */
    public static <K, V> @Nonnull HashMap<K, V> hashMap(Object @Nonnull ... array) {
        return MapKit.hashMap(array);
    }

    /**
     * Returns a new {@link LinkedHashMap} initialing with the given array
     * <p>
     * Every two elements of the array form a key-value pair, that means, the {@code array[0]} and {@code array[1]} will
     * be the first key-value pair, the {@code array[2]} and {@code array[3]} will be the second key-value pair, and so
     * on. If the length of the array is odd and the last key cannot match the value, then the last pair will be the
     * key-{@code null} pair to put.
     * <p>
     * This method is a shortcut to the {@link MapKit#linkedHashMap(Object[])}.
     *
     * @param array the given array
     * @param <K>   the key type
     * @param <V>   the value type
     * @return a new {@link HashMap} initialing with the given array
     * @see MapKit
     */
    public static <K, V> @Nonnull LinkedHashMap<K, V> linkedHashMap(Object @Nonnull ... array) {
        return MapKit.linkedHashMap(array);
    }

    /**
     * Returns a {@link Stream} from the given elements.
     * <p>
     * This method is a shortcut to the {@link StreamKit#stream(Object[])}.
     *
     * @param elements the given elements
     * @param <T>      the component type
     * @return a {@link Stream} from the given elements
     * @see StreamKit
     */
    @SafeVarargs
    public static <T> @Nonnull Stream<T> stream(T @Nonnull ... elements) {
        return StreamKit.stream(elements);
    }

    /**
     * Returns a {@link Stream} from the given elements.
     * <p>
     * This method is a shortcut to the {@link StreamKit#stream(Iterable)}.
     *
     * @param elements the given elements
     * @param <T>      the component type
     * @return a {@link Stream} from the given elements
     * @see StreamKit
     */
    public static <T> @Nonnull Stream<T> stream(@Nonnull Iterable<T> elements) {
        return StreamKit.stream(elements);
    }

    //---------------- Collection End ----------------//

    //---------------- Thread Begin ----------------//

    /**
     * Sleeps the current thread for the specified milliseconds.
     * <p>
     * This method is a shortcut to the {@link ThreadKit#sleep(long)}.
     *
     * @param millis the specified milliseconds
     * @throws AwaitingException if the current thread is interrupted or an error occurs while sleeping
     * @see ThreadKit
     */
    public static void sleep(long millis) throws AwaitingException {
        ThreadKit.sleep(millis);
    }

    /**
     * Sleeps the current thread for the specified duration.
     * <p>
     * This method is a shortcut to the {@link ThreadKit#sleep(Duration)}.
     *
     * @param duration the specified duration
     * @throws AwaitingException if the current thread is interrupted or an error occurs while sleeping
     * @see ThreadKit
     */
    public static void sleep(@Nonnull Duration duration) throws AwaitingException {
        ThreadKit.sleep(duration);
    }

    //---------------- Thread End ----------------//

    //---------------- Process Begin ----------------//

    /**
     * Starts a new process with the specified command, returns the process.
     * <p>
     * This method is a shortcut to the {@link ProcessKit#start(String)}.
     *
     * @param command the specified command
     * @return the process
     * @throws IORuntimeException if any error occurs
     * @see ProcessKit
     */
    public static @Nonnull Process process(@Nonnull String command) throws IORuntimeException {
        return ProcessKit.start(command);
    }

    /**
     * Starts a new process with the specified command and arguments, returns the process.
     * <p>
     * This method is a shortcut to the {@link ProcessKit#start(String...)}.
     *
     * @param command the specified command and arguments
     * @return the process
     * @throws IORuntimeException if any error occurs
     * @see ProcessKit
     */
    public static @Nonnull Process process(@Nonnull String @Nonnull ... command) throws IORuntimeException {
        return ProcessKit.start(command);
    }

    //---------------- Process End ----------------//

    private Fs() {
    }
}