<commit_before>package org.grobid.core.engines;

import org.grobid.core.GrobidModel;
import org.grobid.core.GrobidModels;
import org.grobid.core.analyzers.QuantityAnalyzer;
import org.grobid.core.data.Quantity;
import org.grobid.core.data.Value;
import org.grobid.core.data.ValueBlock;
import org.grobid.core.data.normalization.NormalizationException;
import org.grobid.core.engines.label.QuantitiesTaggingLabels;
import org.grobid.core.engines.label.TaggingLabel;
import org.grobid.core.exceptions.GrobidException;
import org.grobid.core.features.FeaturesVectorValues;
import org.grobid.core.layout.LayoutToken;
import org.grobid.core.tokenization.TaggingTokenCluster;
import org.grobid.core.tokenization.TaggingTokenClusteror;
import org.grobid.core.utilities.LayoutTokensUtil;
import org.grobid.core.utilities.OffsetPosition;
import org.grobid.core.utilities.UnicodeUtil;
import org.grobid.core.utilities.WordsToNumber;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import static org.apache.commons.lang3.StringUtils.*;
import static org.grobid.core.engines.label.QuantitiesTaggingLabels.*;

/**
 * Parser for the value part of a recognized quantity. The goal of the present parser is
 * to recognize and distinguish numerical values, values expressed in letters ("twenty"),
 * exponent of tens (1 x 107), exponent symbol (0.2E-4), and dates ("October 19, 2014 at 20:09 TDB").
 */
public class ValueParser extends AbstractParser {
    private static final Logger LOGGER = LoggerFactory.getLogger(ValueParser.class);

    private static volatile ValueParser instance;

    public static ValueParser getInstance() {
        if (instance == null) {
            getNewInstance();
        }
        return instance;
    }

    private static synchronized void getNewInstance() {
        instance = new ValueParser();
    }

    protected ValueParser() {
        super(QuantitiesModels.VALUES);
    }

    public ValueParser(GrobidModel model) {
        super(model);
    }

    public Value parseValue(String rawValue) {
        return parseValue(rawValue, Locale.ENGLISH);
    }

    public Value parseValue(String rawValue, Locale locale) {
        ValueBlock block = tagValue(rawValue);

        BigDecimal numeric = parseValueBlock(block, locale);
        final Value resultValue = new Value();
        resultValue.setRawValue(rawValue);
        resultValue.setNumeric(numeric);
        resultValue.setStructure(block);

        return resultValue;
    }


    protected BigDecimal parseValueBlock(ValueBlock block, Locale locale) {
        NumberFormat format = NumberFormat.getInstance(locale);

        switch (block.getType()) {
            case NUMBER:
                try {
                    BigDecimal secondPart = null;
                    if (block.getPow() != null && block.getBase() != null) {
                        final Number pow = format.parse(block.getPowAsString());
                        String baseAsString = removeSpacesTabsAndBl(block.getBaseAsString());

                        final BigDecimal baseBd = new BigDecimal(format.parse(baseAsString).toString());
                        final int intPower = pow.intValue();

                        if (intPower < 0) {
                            final BigDecimal powBd = baseBd.pow(-intPower);
                            secondPart = BigDecimal.ONE.divide(powBd, 10, RoundingMode.HALF_UP);
                        } else {
                            secondPart = baseBd.pow(intPower);
                        }
                    }

                    if (block.getNumber() != null) {
                        String numberAsString = removeSpacesTabsAndBl(block.getNumberAsString());
                        final BigDecimal number = new BigDecimal(format.parse(numberAsString).toString());
                        if (secondPart != null) {
                            return number.multiply(secondPart);
                        }
                        return number;
                    } else {
                        return secondPart;
                    }

                } catch (ParseException | ArithmeticException e) {<commit_msg>BigDecimal conversion may also throw NumberFormatException<commit_after>package org.grobid.core.engines;

import org.grobid.core.GrobidModel;
import org.grobid.core.GrobidModels;
import org.grobid.core.analyzers.QuantityAnalyzer;
import org.grobid.core.data.Quantity;
import org.grobid.core.data.Value;
import org.grobid.core.data.ValueBlock;
import org.grobid.core.data.normalization.NormalizationException;
import org.grobid.core.engines.label.QuantitiesTaggingLabels;
import org.grobid.core.engines.label.TaggingLabel;
import org.grobid.core.exceptions.GrobidException;
import org.grobid.core.features.FeaturesVectorValues;
import org.grobid.core.layout.LayoutToken;
import org.grobid.core.tokenization.TaggingTokenCluster;
import org.grobid.core.tokenization.TaggingTokenClusteror;
import org.grobid.core.utilities.LayoutTokensUtil;
import org.grobid.core.utilities.OffsetPosition;
import org.grobid.core.utilities.UnicodeUtil;
import org.grobid.core.utilities.WordsToNumber;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

import static org.apache.commons.lang3.StringUtils.*;
import static org.grobid.core.engines.label.QuantitiesTaggingLabels.*;

/**
 * Parser for the value part of a recognized quantity. The goal of the present parser is
 * to recognize and distinguish numerical values, values expressed in letters ("twenty"),
 * exponent of tens (1 x 107), exponent symbol (0.2E-4), and dates ("October 19, 2014 at 20:09 TDB").
 */
public class ValueParser extends AbstractParser {
    private static final Logger LOGGER = LoggerFactory.getLogger(ValueParser.class);

    private static volatile ValueParser instance;

    public static ValueParser getInstance() {
        if (instance == null) {
            getNewInstance();
        }
        return instance;
    }

    private static synchronized void getNewInstance() {
        instance = new ValueParser();
    }

    protected ValueParser() {
        super(QuantitiesModels.VALUES);
    }

    public ValueParser(GrobidModel model) {
        super(model);
    }

    public Value parseValue(String rawValue) {
        return parseValue(rawValue, Locale.ENGLISH);
    }

    public Value parseValue(String rawValue, Locale locale) {
        ValueBlock block = tagValue(rawValue);

        BigDecimal numeric = parseValueBlock(block, locale);
        final Value resultValue = new Value();
        resultValue.setRawValue(rawValue);
        resultValue.setNumeric(numeric);
        resultValue.setStructure(block);

        return resultValue;
    }


    protected BigDecimal parseValueBlock(ValueBlock block, Locale locale) {
        NumberFormat format = NumberFormat.getInstance(locale);

        switch (block.getType()) {
            case NUMBER:
                try {
                    BigDecimal secondPart = null;
                    if (block.getPow() != null && block.getBase() != null) {
                        final Number pow = format.parse(block.getPowAsString());
                        String baseAsString = removeSpacesTabsAndBl(block.getBaseAsString());

                        final BigDecimal baseBd = new BigDecimal(format.parse(baseAsString).toString());
                        final int intPower = pow.intValue();

                        if (intPower < 0) {
                            final BigDecimal powBd = baseBd.pow(-intPower);
                            secondPart = BigDecimal.ONE.divide(powBd, 10, RoundingMode.HALF_UP);
                        } else {
                            secondPart = baseBd.pow(intPower);
                        }
                    }

                    if (block.getNumber() != null) {
                        String numberAsString = removeSpacesTabsAndBl(block.getNumberAsString());
                        final BigDecimal number = new BigDecimal(format.parse(numberAsString).toString());
                        if (secondPart != null) {
                            return number.multiply(secondPart);
                        }
                        return number;
                    } else {
                        return secondPart;
                    }

                } catch (ParseException | ArithmeticException | NumberFormatException e) {
{'fraction_non_alphanumeric': 0.0897861146059705, 'fraction_numerical': 0.005261351938693812, 'mean_word_length': 2.4452324665090623, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 3, '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': '6267806', 'n_tokens_mistral': 2371, 'n_tokens_neox': 2248, 'n_words': 514}