<commit_before>package name.abuchen.portfolio.money;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.Locale;

public abstract class Values<E>
{
    public static final MathContext MC = new MathContext(10, RoundingMode.HALF_UP);

    public static final class MoneyValues extends Values<Money>
    {
        private MoneyValues()
        {
            super("#,##0.00", 2); //$NON-NLS-1$
        }

        @Override
        public String format(Money amount)
        {
            return String.format("%s %,.2f", amount.getCurrencyCode(), amount.getAmount() / divider()); //$NON-NLS-1$
        }

        public String format(Money amount, String skipCurrencyCode)
        {
            if (skipCurrencyCode.equals(amount.getCurrencyCode()))
                return String.format("%,.2f", amount.getAmount() / divider()); //$NON-NLS-1$
            else
                return format(amount);
        }

        @Override
        public String formatNonZero(Money amount)
        {
            return amount == null || amount.isZero() ? null : format(amount);
        }

        @Override
        public String formatNonZero(Money amount, double threshold)
        {
            boolean isNotZero = amount != null && Math.abs(amount.getAmount()) >= threshold;
            return isNotZero ? format(amount) : null;
        }

        public String formatNonZero(Money amount, String skipCurrencyCode)
        {
            return amount == null || amount.isZero() ? null : format(amount, skipCurrencyCode);
        }
    }

    public static final class QuoteValues extends Values<Long>
    {
        private static final String QUOTE_PATTERN = "#,##0.00######"; //$NON-NLS-1$

        private static final ThreadLocal<DecimalFormat> QUOTE_FORMAT = ThreadLocal // NOSONAR
                        .withInitial(() -> new DecimalFormat(QUOTE_PATTERN));

        private final BigDecimal factorToMoney;
        private final int precisionDeltaToMoney;

        private QuoteValues()
        {
            super(QUOTE_PATTERN, 8);

            factorToMoney = BigDecimal.valueOf(factor() / Values.Money.factor());
            precisionDeltaToMoney = precision() - Values.Money.precision();
        }

        @Override
        public String format(Long quote)
        {
            return QUOTE_FORMAT.get().format(quote / divider());
        }

        public String format(String currencyCode, long quote, String skipCurrency)
        {
            if (currencyCode == null || skipCurrency.equals(currencyCode))
                return format(quote);
            else
                return format(currencyCode, quote);
        }

        public String format(String currencyCode, long quote)
        {
            return currencyCode + " " + format(quote); //$NON-NLS-1$
        }

        public String format(Quote quote)
        {
            return format(quote.getCurrencyCode(), quote.getAmount());
        }

        public String format(Quote quote, String skipCurrency)
        {
            return format(quote.getCurrencyCode(), quote.getAmount(), skipCurrency);
        }

        public String formatNonZero(Quote amount, String skipCurrencyCode)
        {
            return amount == null || amount.isZero() ? null : format(amount, skipCurrencyCode);
        }

        /**
         * Factor by which to multiply a monetary amount to convert it into a
         * quote amount. Monetary amounts have 2 decimal digits while quotes
         * have 4 digits.
         */
        public int factorToMoney()
        {
            return factor() / Values.Money.factor();
        }

        /**
         * Divider by which to divide a quote amount to convert it into a
         * monetary amount. Monetary amounts have 2 decimal digits while quotes
         * have 4 digits.
         */
        public double dividerToMoney()
        {
            return divider() / Values.Money.divider();
        }

        public BigDecimal getBigDecimalFactorToMoney()
        {
            return factorToMoney;
        }

        public int precisionDeltaToMoney()
        {
            return precisionDeltaToMoney;
        }
    }

    public static final Values<Long> Amount = new Values<Long>("#,##0.00", 2) //$NON-NLS-1$
    {
        @Override
        public String format(Long amount)
        {
            return String.format("%,.2f", amount / divider()); //$NON-NLS-1$
        }
    };

    public static final MoneyValues Money = new MoneyValues(); // NOSONAR

    public static final Values<Long> AmountFraction = new Values<Long>("#,##0.00###", 5) //$NON-NLS-1$
    {
        private final DecimalFormat format = new DecimalFormat(pattern());

        @Override
        public String format(Long share)
        {
            return format.format(share / divider());
        }
    };

    /**
     * Optionally format values without decimal places. Currently used only for
     * attributes attached to the security.
     */
    public static final Values<Long> AmountPlain = new Values<Long>("#,##0.##", 2) //$NON-NLS-1$
    {
        private final DecimalFormat format = new DecimalFormat(pattern());

        @Override
        public String format(Long amount)
        {
            return format.format(amount / divider());
        }
    };

    public static final Values<Long> AmountShort = new Values<Long>("#,##0", 2) //$NON-NLS-1$
    {
        private final DecimalFormat format = new DecimalFormat(pattern());

        @Override
        public String format(Long amount)
        {
            return format.format(amount / divider());
        }
    };

    public static final Values<Long> Share = new Values<Long>("#,##0.######", 8) //$NON-NLS-1$
    {
        private final DecimalFormat format = new DecimalFormat(pattern());

        @Override
        public String format(Long share)
        {
            return format.format(share / divider());
        }<commit_msg>Fixed formatting of shares to include all 8 digits<commit_after>package name.abuchen.portfolio.money;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;
import java.util.Locale;

public abstract class Values<E>
{
    public static final MathContext MC = new MathContext(10, RoundingMode.HALF_UP);

    public static final class MoneyValues extends Values<Money>
    {
        private MoneyValues()
        {
            super("#,##0.00", 2); //$NON-NLS-1$
        }

        @Override
        public String format(Money amount)
        {
            return String.format("%s %,.2f", amount.getCurrencyCode(), amount.getAmount() / divider()); //$NON-NLS-1$
        }

        public String format(Money amount, String skipCurrencyCode)
        {
            if (skipCurrencyCode.equals(amount.getCurrencyCode()))
                return String.format("%,.2f", amount.getAmount() / divider()); //$NON-NLS-1$
            else
                return format(amount);
        }

        @Override
        public String formatNonZero(Money amount)
        {
            return amount == null || amount.isZero() ? null : format(amount);
        }

        @Override
        public String formatNonZero(Money amount, double threshold)
        {
            boolean isNotZero = amount != null && Math.abs(amount.getAmount()) >= threshold;
            return isNotZero ? format(amount) : null;
        }

        public String formatNonZero(Money amount, String skipCurrencyCode)
        {
            return amount == null || amount.isZero() ? null : format(amount, skipCurrencyCode);
        }
    }

    public static final class QuoteValues extends Values<Long>
    {
        private static final String QUOTE_PATTERN = "#,##0.00######"; //$NON-NLS-1$

        private static final ThreadLocal<DecimalFormat> QUOTE_FORMAT = ThreadLocal // NOSONAR
                        .withInitial(() -> new DecimalFormat(QUOTE_PATTERN));

        private final BigDecimal factorToMoney;
        private final int precisionDeltaToMoney;

        private QuoteValues()
        {
            super(QUOTE_PATTERN, 8);

            factorToMoney = BigDecimal.valueOf(factor() / Values.Money.factor());
            precisionDeltaToMoney = precision() - Values.Money.precision();
        }

        @Override
        public String format(Long quote)
        {
            return QUOTE_FORMAT.get().format(quote / divider());
        }

        public String format(String currencyCode, long quote, String skipCurrency)
        {
            if (currencyCode == null || skipCurrency.equals(currencyCode))
                return format(quote);
            else
                return format(currencyCode, quote);
        }

        public String format(String currencyCode, long quote)
        {
            return currencyCode + " " + format(quote); //$NON-NLS-1$
        }

        public String format(Quote quote)
        {
            return format(quote.getCurrencyCode(), quote.getAmount());
        }

        public String format(Quote quote, String skipCurrency)
        {
            return format(quote.getCurrencyCode(), quote.getAmount(), skipCurrency);
        }

        public String formatNonZero(Quote amount, String skipCurrencyCode)
        {
            return amount == null || amount.isZero() ? null : format(amount, skipCurrencyCode);
        }

        /**
         * Factor by which to multiply a monetary amount to convert it into a
         * quote amount. Monetary amounts have 2 decimal digits while quotes
         * have 4 digits.
         */
        public int factorToMoney()
        {
            return factor() / Values.Money.factor();
        }

        /**
         * Divider by which to divide a quote amount to convert it into a
         * monetary amount. Monetary amounts have 2 decimal digits while quotes
         * have 4 digits.
         */
        public double dividerToMoney()
        {
            return divider() / Values.Money.divider();
        }

        public BigDecimal getBigDecimalFactorToMoney()
        {
            return factorToMoney;
        }

        public int precisionDeltaToMoney()
        {
            return precisionDeltaToMoney;
        }
    }

    public static final Values<Long> Amount = new Values<Long>("#,##0.00", 2) //$NON-NLS-1$
    {
        @Override
        public String format(Long amount)
        {
            return String.format("%,.2f", amount / divider()); //$NON-NLS-1$
        }
    };

    public static final MoneyValues Money = new MoneyValues(); // NOSONAR

    public static final Values<Long> AmountFraction = new Values<Long>("#,##0.00###", 5) //$NON-NLS-1$
    {
        private final DecimalFormat format = new DecimalFormat(pattern());

        @Override
        public String format(Long share)
        {
            return format.format(share / divider());
        }
    };

    /**
     * Optionally format values without decimal places. Currently used only for
     * attributes attached to the security.
     */
    public static final Values<Long> AmountPlain = new Values<Long>("#,##0.##", 2) //$NON-NLS-1$
    {
        private final DecimalFormat format = new DecimalFormat(pattern());

        @Override
        public String format(Long amount)
        {
            return format.format(amount / divider());
        }
    };

    public static final Values<Long> AmountShort = new Values<Long>("#,##0", 2) //$NON-NLS-1$
    {
        private final DecimalFormat format = new DecimalFormat(pattern());

        @Override
        public String format(Long amount)
        {
            return format.format(amount / divider());
        }
    };

    public static final Values<Long> Share = new Values<Long>("#,##0.########", 8) //$NON-NLS-1$
    {
        private final DecimalFormat format = new DecimalFormat(pattern());

        @Override
        public String format(Long share)
        {
            return format.format(share / divider());
        }
{'fraction_non_alphanumeric': 0.10875352964905204, 'fraction_numerical': 0.006857603872529245, 'mean_word_length': 2.082815220094504, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 35, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4441892', 'n_tokens_mistral': 3415, 'n_tokens_neox': 3213, 'n_words': 874}