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

com.landawn.abacus.util.Wrapper Maven / Gradle / Ivy

Go to download

A general programming library in Java/Android. It's easy to learn and simple to use with concise and powerful APIs.

There is a newer version: 5.2.4
Show newest version
/*
 * Copyright (c) 2015, Haiyang Li.
 *
 * 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 com.landawn.abacus.util;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiPredicate;
import java.util.function.Function;
import java.util.function.ToIntFunction;

/**
 *
 * @author Haiyang Li
 * @param 
 * @since 0.8
 * @see Keyed
 */
@com.landawn.abacus.annotation.Immutable
public final class Wrapper implements Immutable {

    static final ToIntFunction arrayHashFunction = N::deepHashCode;

    static final BiPredicate arrayEqualsFunction = N::deepEquals;

    private final T value;

    private final ToIntFunction hashFunction;

    private final BiPredicate equalsFunction;

    private final Function toStringFunction;

    private int hashCode;

    private Wrapper(T value, ToIntFunction hashFunction, BiPredicate equalsFunction) {
        this(value, hashFunction, equalsFunction, null);
    }

    private Wrapper(T value, ToIntFunction hashFunction, BiPredicate equalsFunction,
            Function toStringFunction) {
        this.value = value;
        this.hashFunction = hashFunction;
        this.equalsFunction = equalsFunction;
        this.toStringFunction = toStringFunction;

    }

    @SuppressWarnings("rawtypes")
    private static final Wrapper WRAPPER_FOR_NULL_ARRAY = new Wrapper<>(null, arrayHashFunction, arrayEqualsFunction);

    @SuppressWarnings("rawtypes")
    private static final Map arrayWapperPool = new ConcurrentHashMap<>();

    static {
        arrayWapperPool.put(boolean.class, new Wrapper<>(new boolean[0], arrayHashFunction, arrayEqualsFunction));
    }

    /**
     *
     * @param 
     * @param array
     * @return
     */
    public static  Wrapper of(T array) {
        if (array == null) {
            return WRAPPER_FOR_NULL_ARRAY;
        }

        Wrapper result = null;

        if (array.getClass().isArray() && java.lang.reflect.Array.getLength(array) == 0) {
            result = arrayWapperPool.get(array.getClass().getComponentType());

            if (result == null) {
                result = new Wrapper<>(array, arrayHashFunction, arrayEqualsFunction);
                arrayWapperPool.put(array.getClass().getComponentType(), result);
            }

            return result;
        }

        // return new Wrapper(checkArray(array), arrayHashFunction, arrayEqualsFunction);
        return new Wrapper<>(array, arrayHashFunction, arrayEqualsFunction);
    }

    /**
     *
     * @param 
     * @param value
     * @param hashFunction
     * @param equalsFunction
     * @return
     */
    public static  Wrapper of(T value, ToIntFunction hashFunction, BiPredicate equalsFunction) {
        N.checkArgNotNull(hashFunction, "hashFunction");
        N.checkArgNotNull(equalsFunction, "equalsFunction");

        return new Wrapper<>(value, hashFunction, equalsFunction);
    }

    /**
     *
     * @param 
     * @param value
     * @param hashFunction
     * @param equalsFunction
     * @param toStringFunction
     * @return
     */
    public static  Wrapper of(T value, ToIntFunction hashFunction, BiPredicate equalsFunction,
            Function toStringFunction) {
        N.checkArgNotNull(hashFunction, "hashFunction");
        N.checkArgNotNull(equalsFunction, "equalsFunction");
        N.checkArgNotNull(toStringFunction, "toStringFunction");

        return new Wrapper<>(value, hashFunction, equalsFunction, toStringFunction);
    }

    /**
     * 
     *
     * @return 
     */
    public T value() {
        return value;
    }

    //    static  T checkArray(T a) {
    //        if (a != null && a.getClass().isArray() == false) {
    //            throw new IllegalArgumentException(a.getClass().getCanonicalName() + " is not array type");
    //        }
    //
    //        return a;
    //    }

    /**
     * 
     *
     * @return 
     */
    @Override
    public int hashCode() {
        if (hashCode == 0) {
            hashCode = value == null ? 0 : hashFunction.applyAsInt(value);
        }

        return hashCode;
    }

    /**
     *
     * @param obj
     * @return
     */
    @Override
    public boolean equals(Object obj) {
        return (obj == this) || (obj instanceof Wrapper && equalsFunction.test(((Wrapper) obj).value, value));
    }

    /**
     * 
     *
     * @return 
     */
    @Override
    public String toString() {
        if (toStringFunction == null) {
            if (value == null) {
                return "Wrapper[null]";
            } else {
                return String.format("Wrapper[%s]", N.toString(value));
            }
        } else {
            return toStringFunction.apply(value);
        }
    }
}