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

jsonvalues.JsBigDec Maven / Gradle / Ivy

package jsonvalues;


import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.OptionalLong;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;

import static java.util.Objects.requireNonNull;

/**
 Represents an immutable json number of type BigDecimal.
 */
public final class JsBigDec extends JsNumber implements Comparable {

    public static final int ID = 8;

    /**
     prism between the sum type JsValue and JsBigDec
     */
    public static Prism prism = new Prism<>(s ->
                                                                 {
                                                                     if (s.isDouble())
                                                                         return Optional.of(BigDecimal.valueOf(s.toJsDouble().value));
                                                                     if (s.isBigDec())
                                                                         return Optional.of(s.toJsBigDec().value);
                                                                     return Optional.empty();
                                                                 },
                                                                 JsBigDec::of
    );
    /**
     The big decimal value
     */
    public final BigDecimal value;

    private JsBigDec(final BigDecimal value) {
        this.value = value;
    }

    @Override
    public int id() {
        return ID;
    }

    @Override
    public boolean isBigDec() {
        return true;
    }

    /**
     Compares two {@code JsBigDec} objects numerically

     @see JsBigDec#compareTo(JsBigDec)
     */
    @Override
    public int compareTo(final JsBigDec o) {
        return value.compareTo(requireNonNull(o).value);
    }

    /**
     Returns the hashcode of this json big decimal

     @return the hashcode of this JsBigDec
     */
    @Override
    public int hashCode() {
        final OptionalInt optInt = intValueExact();
        if (optInt.isPresent()) return optInt.getAsInt();

        final OptionalLong optLong = longValueExact();
        if (optLong.isPresent()) return JsLong.of(optLong.getAsLong())
                                              .hashCode();

        final Optional optBigInt = bigIntegerExact();
        return optBigInt.map(BigInteger::hashCode)
                        .orElseGet(value::hashCode);

    }

    /**
     Indicates whether some other object is "equal to" this json big decimal. Numbers of different
     types are equals if the have the same value.

     @param that the reference object with which to compare.
     @return true if that is a JsNumber with the same value as this
     */
    @Override
    public boolean equals(Object that) {
        if (this == that) return true;
        if (that == null) return false;
        if (!(that instanceof JsNumber)) return false;
        final JsNumber number = (JsNumber) that;
        if (number.isBigDec()) return value.compareTo(number.toJsBigDec().value) == 0;
        if (number.isBigInt()) return equals(number.toJsBigInt());
        if (number.isInt()) return equals(number.toJsInt());
        if (number.isLong()) return equals(number.toJsLong());
        if (number.isDouble()) return equals(number.toJsDouble());
        return false;
    }

    /**
     @return a string representation of the bigdec value
     @see BigDecimal#toString() BigDecimal.toString
     */
    @Override
    public String toString() {
        return value.toString();
    }

    /**
     returns true if this bigdecimal and the specified biginteger represent the same number

     @param jsBigInt the specified JsBigInt
     @return true if both JsValue are the same value
     */
    boolean equals(JsBigInt jsBigInt) {
        final Optional optional = bigIntegerExact();
        return optional.isPresent() && optional.get()
                                               .equals(requireNonNull(jsBigInt).value);
    }

    /**
     returns true if this bigdecimal and the specified integer represent the same number

     @param jsInt the specified JsInt
     @return true if both JsValue are the same value
     */
    boolean equals(JsInt jsInt) {
        final OptionalInt optional = intValueExact();
        return optional.isPresent() && optional.getAsInt() == requireNonNull(jsInt).value;
    }

    /**
     returns true if this bigdecimal and the specified long represent the same number

     @param jsLong the specified JsLong
     @return true if both JsValue are the same value
     */
    boolean equals(JsLong jsLong) {
        final OptionalLong optional = longValueExact();
        return optional.isPresent() && optional.getAsLong() == requireNonNull(jsLong).value;
    }

    /**
     returns true if this bigdecimal and the specified double represent the same number

     @param jsDouble the specified JsDouble
     @return true if both JsValue are the same value
     */
    boolean equals(JsDouble jsDouble) {

        //errorProne warning BigDecimalEquals -> compareTo instead of equals so 2.0 = 2.000
        return BigDecimal.valueOf(requireNonNull(jsDouble).value)
                         .compareTo(value) == 0;
    }

    /**
     Returns the value of this bigdecimal; or an empty optional if the value overflows an {@code biginteger}.

     @return this bigdecimal as an biginteger wrapped in an OptionalInt
     */
    Optional bigIntegerExact() {
        try {
            return Optional.of(value.toBigIntegerExact());
        } catch (ArithmeticException e) {
            return Optional.empty();
        }

    }

    /**
     Returns the value of this bigdecimal; or an empty optional if the value overflows an {@code int}.

     @return this bigdecimal as an int wrapped in an OptionalInt
     */
    OptionalInt intValueExact() {
        try {
            return OptionalInt.of(value.intValueExact());
        } catch (ArithmeticException e) {
            return OptionalInt.empty();
        }
    }

    /**
     Returns the value of this bigdecimal; or an empty optional if the value overflows an {@code long}.

     @return this bigdecimal as an long wrapped in an OptionalLong
     */
    OptionalLong longValueExact() {
        try {
            return OptionalLong.of(value.longValueExact());
        } catch (ArithmeticException e) {
            return OptionalLong.empty();
        }

    }

    /**
     Maps this JsBigDec into another one

     @param fn the mapping function
     @return a new JsBigDec
     */
    public JsBigDec map(UnaryOperator fn) {
        return JsBigDec.of(requireNonNull(fn).apply(value));
    }

    /**
     Static factory method to create a JsBigDec from a BigDecimal object.

     @param n the big decimal
     @return a new JsBigDec
     */
    public static JsBigDec of(BigDecimal n) {
        return new JsBigDec(requireNonNull(n));
    }

    /**
     Tests the value of this json bigdec on a predicate

     @param predicate the predicate
     @return true if this big decimal satisfies the predicate
     */
    public boolean test(Predicate predicate) {
        return predicate.test(value);
    }

    /**
     Returns the value of this bigdecimal; or an empty optional if the value overflows an {@code double}.

     @return this bigdecimal as an double wrapped in an OptionalDouble
     @see BigDecimal#doubleValue()
     */
    Optional doubleValueExact() {
        final double value = this.value.doubleValue();
        if (value == Double.NEGATIVE_INFINITY) return Optional.empty();
        if (value == Double.POSITIVE_INFINITY) return Optional.empty();
        return Optional.of(value);

    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy