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

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

There is a newer version: 1.10.1
Show newest version
/*
 * Copyright (c) 2017, 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.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.Set;

import com.landawn.abacus.util.function.Supplier;
import com.landawn.abacus.util.stream.Stream;

public final class Nullable {
    private static final Nullable EMPTY = new Nullable<>();

    private final T value;
    private final boolean isPresent;

    private Nullable() {
        this.value = null;
        this.isPresent = false;
    }

    private Nullable(T value) {
        this.value = value;
        this.isPresent = true;
    }

    public static  Nullable empty() {
        return (Nullable) EMPTY;
    }

    public static  Nullable of(T value) {
        return new Nullable<>(value);
    }

    public static  Nullable from(Optional optional) {
        if (optional.isPresent()) {
            return new Nullable<>(optional.get());
        } else {
            return Nullable. empty();
        }
    }

    public T get() throws NoSuchElementException {
        return orElseThrow();
    }

    /**
     * Returns {@code true} if the value is present, otherwise returns {@code false}.
     * 
     * @return
     */
    public boolean isPresent() {
        return isPresent;
    }

    /**
     * Returns {@code true} if the value is not present, otherwise returns {@code false}.
     * 
     * @return
     */
    public boolean isNotPresent() {
        return isPresent == false;
    }

    /**
     * Returns {@code true} if the value is not present, otherwise returns {@code false}.
     * 
     * @return
     * @deprecated replaced by {@link #isNotPresent()}
     */
    @Deprecated
    public boolean isEmpty() {
        return isPresent == false;
    }

    /**
     * Returns {@code true} if the value is not present, or it is present but it's {@code null}, otherwise returns {@code false}.
     * 
     * @return
     */
    public boolean isNull() {
        return value == null;
    }

    /**
     * Returns {@code true} if the value is present and it's not {@code null}, otherwise returns {@code false}.
     * 
     * @return
     */
    public boolean isNotNull() {
        return value != null;
    }

    /**
     * 
     * @param action
     * @return itself
     * @throws E
     */
    public  Nullable ifPresent(Try.Consumer action) throws E {
        Objects.requireNonNull(action);

        if (isPresent()) {
            action.accept(value);
        }

        return this;
    }

    /**
     * 
     * @param action
     * @param emptyAction
     * @return itself
     * @throws E
     * @throws E2
     */
    public  Nullable ifPresentOrElse(Try.Consumer action, Try.Runnable emptyAction)
            throws E, E2 {
        Objects.requireNonNull(action);
        Objects.requireNonNull(emptyAction);

        if (isPresent()) {
            action.accept(value);
        } else {
            emptyAction.run();
        }

        return this;
    }

    /**
     * 
     * @param action
     * @return itself
     * @throws E
     */
    public  Nullable ifNotNull(Try.Consumer action) throws E {
        Objects.requireNonNull(action);

        if (isNotNull()) {
            action.accept(value);
        }

        return this;
    }

    /**
     * 
     * @param action
     * @param emptyAction
     * @return itself
     * @throws E
     * @throws E2
     */
    public  Nullable ifNotNullOrElse(Try.Consumer action, Try.Runnable emptyAction)
            throws E, E2 {
        Objects.requireNonNull(action);
        Objects.requireNonNull(emptyAction);

        if (isNotNull()) {
            action.accept(value);
        } else {
            emptyAction.run();
        }

        return this;
    }

    public  Nullable filter(Try.Predicate predicate) throws E {
        Objects.requireNonNull(predicate);

        if (isPresent() && predicate.test(value)) {
            return this;
        } else {
            return empty();
        }
    }

    public  Optional filterIfNotNull(Try.Predicate predicate) throws E {
        Objects.requireNonNull(predicate);

        if (isNotNull() && predicate.test(value)) {
            return Optional.of(value);
        } else {
            return Optional.empty();
        }
    }

    public  Nullable map(Try.Function mapper) throws E {
        Objects.requireNonNull(mapper);

        if (isPresent()) {
            return Nullable.of((U) mapper.apply(value));
        } else {
            return empty();
        }
    }

    public  OptionalBoolean mapToBoolean(final Try.ToBooleanFunction mapper) throws E {
        Objects.requireNonNull(mapper);

        if (isPresent()) {
            return OptionalBoolean.of(mapper.applyAsBoolean(value));
        } else {
            return OptionalBoolean.empty();
        }
    }

    public  OptionalChar mapToChar(final Try.ToCharFunction mapper) throws E {
        Objects.requireNonNull(mapper);

        if (isPresent()) {
            return OptionalChar.of(mapper.applyAsChar(value));
        } else {
            return OptionalChar.empty();
        }
    }

    public  OptionalByte mapToByte(final Try.ToByteFunction mapper) throws E {
        Objects.requireNonNull(mapper);

        if (isPresent()) {
            return OptionalByte.of(mapper.applyAsByte(value));
        } else {
            return OptionalByte.empty();
        }
    }

    public  OptionalShort mapToShort(final Try.ToShortFunction mapper) throws E {
        Objects.requireNonNull(mapper);

        if (isPresent()) {
            return OptionalShort.of(mapper.applyAsShort(value));
        } else {
            return OptionalShort.empty();
        }
    }

    public  OptionalInt mapToInt(final Try.ToIntFunction mapper) throws E {
        Objects.requireNonNull(mapper);

        if (isPresent()) {
            return OptionalInt.of(mapper.applyAsInt(value));
        } else {
            return OptionalInt.empty();
        }
    }

    public  OptionalLong mapToLong(final Try.ToLongFunction mapper) throws E {
        Objects.requireNonNull(mapper);

        if (isPresent()) {
            return OptionalLong.of(mapper.applyAsLong(value));
        } else {
            return OptionalLong.empty();
        }
    }

    public  OptionalFloat mapToFloat(final Try.ToFloatFunction mapper) throws E {
        Objects.requireNonNull(mapper);

        if (isPresent()) {
            return OptionalFloat.of(mapper.applyAsFloat(value));
        } else {
            return OptionalFloat.empty();
        }
    }

    public  OptionalDouble mapToDouble(final Try.ToDoubleFunction mapper) throws E {
        Objects.requireNonNull(mapper);

        if (isPresent()) {
            return OptionalDouble.of(mapper.applyAsDouble(value));
        } else {
            return OptionalDouble.empty();
        }
    }

    public  Nullable mapIfNotNull(Try.Function mapper) throws E {
        Objects.requireNonNull(mapper);

        if (isNotNull()) {
            return Nullable.of((U) mapper.apply(value));
        } else {
            return empty();
        }
    }

    public  OptionalBoolean mapToBooleanIfNotNull(final Try.ToBooleanFunction mapper) throws E {
        Objects.requireNonNull(mapper);

        if (isNotNull()) {
            return OptionalBoolean.of(mapper.applyAsBoolean(value));
        } else {
            return OptionalBoolean.empty();
        }
    }

    public  OptionalChar mapToCharIfNotNull(final Try.ToCharFunction mapper) throws E {
        Objects.requireNonNull(mapper);

        if (isNotNull()) {
            return OptionalChar.of(mapper.applyAsChar(value));
        } else {
            return OptionalChar.empty();
        }
    }

    public  OptionalByte mapToByteIfNotNull(final Try.ToByteFunction mapper) throws E {
        Objects.requireNonNull(mapper);

        if (isNotNull()) {
            return OptionalByte.of(mapper.applyAsByte(value));
        } else {
            return OptionalByte.empty();
        }
    }

    public  OptionalShort mapToShortIfNotNull(final Try.ToShortFunction mapper) throws E {
        Objects.requireNonNull(mapper);

        if (isNotNull()) {
            return OptionalShort.of(mapper.applyAsShort(value));
        } else {
            return OptionalShort.empty();
        }
    }

    public  OptionalInt mapToIntIfNotNull(final Try.ToIntFunction mapper) throws E {
        Objects.requireNonNull(mapper);

        if (isNotNull()) {
            return OptionalInt.of(mapper.applyAsInt(value));
        } else {
            return OptionalInt.empty();
        }
    }

    public  OptionalLong mapToLongIfNotNull(final Try.ToLongFunction mapper) throws E {
        Objects.requireNonNull(mapper);

        if (isNotNull()) {
            return OptionalLong.of(mapper.applyAsLong(value));
        } else {
            return OptionalLong.empty();
        }
    }

    public  OptionalFloat mapToFloatIfNotNull(final Try.ToFloatFunction mapper) throws E {
        Objects.requireNonNull(mapper);

        if (isNotNull()) {
            return OptionalFloat.of(mapper.applyAsFloat(value));
        } else {
            return OptionalFloat.empty();
        }
    }

    public  OptionalDouble mapToDoubleIfNotNull(final Try.ToDoubleFunction mapper) throws E {
        Objects.requireNonNull(mapper);

        if (isNotNull()) {
            return OptionalDouble.of(mapper.applyAsDouble(value));
        } else {
            return OptionalDouble.empty();
        }
    }

    public  Nullable flatMap(Try.Function, E> mapper) throws E {
        Objects.requireNonNull(mapper);

        if (isPresent()) {
            return Objects.requireNonNull(mapper.apply(value));
        } else {
            return empty();
        }
    }

    public  Nullable flatMapIfNotNull(Try.Function, E> mapper) throws E {
        Objects.requireNonNull(mapper);

        if (isNotNull()) {
            return Objects.requireNonNull(mapper.apply(value));
        } else {
            return empty();
        }
    }

    public  Nullable or(Try.Supplier, E> supplier) throws E {
        Objects.requireNonNull(supplier);

        if (isPresent()) {
            return this;
        } else {
            return Objects.requireNonNull((Nullable) supplier.get());
        }
    }

    public  Nullable orIfNull(Try.Supplier, E> supplier) throws E {
        Objects.requireNonNull(supplier);

        if (isNotNull()) {
            return this;
        } else {
            return Objects.requireNonNull((Nullable) supplier.get());
        }
    }

    public T orNull() {
        return isPresent() ? value : null;
    }

    //    public T orElseNull() {
    //        return isPresent() ? value : null;
    //    }

    public T orElse(T other) {
        return isPresent() ? value : other;
    }

    public  T orElseGet(Try.Supplier other) throws E {
        Objects.requireNonNull(other);

        if (isPresent()) {
            return value;
        } else {
            return other.get();
        }
    }

    public T orElseThrow() throws NoSuchElementException {
        if (isPresent()) {
            return value;
        } else {
            throw new NoSuchElementException("No value is present");
        }
    }

    public  T orElseThrow(Supplier exceptionSupplier) throws X {
        Objects.requireNonNull(exceptionSupplier);

        if (isPresent()) {
            return value;
        } else {
            throw exceptionSupplier.get();
        }
    }

    public T orElseIfNull(T other) {
        return isNotNull() ? value : other;
    }

    public  T orElseGetIfNull(Try.Supplier other) throws E {
        Objects.requireNonNull(other);

        if (isNotNull()) {
            return value;
        } else {
            return other.get();
        }
    }

    public T orElseThrowIfNull() throws NoSuchElementException {
        if (isNotNull()) {
            return value;
        } else {
            throw new NoSuchElementException("No value is present");
        }
    }

    public  T orElseThrowIfNull(Supplier exceptionSupplier) throws X {
        Objects.requireNonNull(exceptionSupplier);

        if (isNotNull()) {
            return value;
        } else {
            throw exceptionSupplier.get();
        }
    }

    public Stream stream() {
        if (isPresent()) {
            return Stream.of(value);
        } else {
            return Stream. empty();
        }
    }

    public Stream streamIfNotNull() {
        if (isNotNull()) {
            return Stream.of(value);
        } else {
            return Stream. empty();
        }
    }

    public List toList() {
        if (isPresent()) {
            return N.asList(value);
        } else {
            return new ArrayList<>();
        }
    }

    public List toListIfNotNull() {
        if (isNotNull()) {
            return N.asList(value);
        } else {
            return new ArrayList<>();
        }
    }

    public Set toSet() {
        if (isPresent()) {
            return N.asSet(value);
        } else {
            return new HashSet<>();
        }
    }

    public Set toSetIfNotNull() {
        if (isNotNull()) {
            return N.asSet(value);
        } else {
            return new HashSet<>();
        }
    }

    public ImmutableList toImmutableList() {
        if (isPresent()) {
            return ImmutableList.of(value);
        } else {
            return ImmutableList.empty();
        }
    }

    public ImmutableList toImmutableListIfNotNull() {
        if (isNotNull()) {
            return ImmutableList.of(value);
        } else {
            return ImmutableList.empty();
        }
    }

    public ImmutableSet toImmutableSet() {
        if (isPresent()) {
            return ImmutableSet.of(value);
        } else {
            return ImmutableSet.empty();
        }
    }

    public ImmutableSet toImmutableSetIfNotNull() {
        if (isNotNull()) {
            return ImmutableSet.of(value);
        } else {
            return ImmutableSet.empty();
        }
    }

    public Optional toOptional() {
        if (value == null) {
            return Optional. empty();
        } else {
            return Optional.of(value);
        }
    }

    public java.util.Optional toJdkOptional() {
        if (value == null) {
            return java.util.Optional. empty();
        } else {
            return java.util.Optional.of(value);
        }
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }

        if (obj instanceof Nullable) {
            final Nullable other = (Nullable) obj;

            return N.equals(isPresent, other.isPresent) && N.equals(value, other.value);
        }

        return false;
    }

    @Override
    public int hashCode() {
        return N.hashCode(isPresent) * 31 + N.hashCode(value);
    }

    @Override
    public String toString() {
        if (value == null) {
            return isPresent ? "Nullable[null]" : "Nullable.empty";
        } else {
            return String.format("Nullable[%s]", value);
        }
    }
}