001// --------------------------------------------------------------------------------
002// Copyright 2002-2024 Echo Three, LLC
003//
004// Licensed under the Apache License, Version 2.0 (the "License");
005// you may not use this file except in compliance with the License.
006// You may obtain a copy of the License at
007//
008//     http://www.apache.org/licenses/LICENSE-2.0
009//
010// Unless required by applicable law or agreed to in writing, software
011// distributed under the License is distributed on an "AS IS" BASIS,
012// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013// See the License for the specific language governing permissions and
014// limitations under the License.
015// --------------------------------------------------------------------------------
016
017package com.echothree.util.common.string;
018
019public class DecimalUtils {
020
021    private DecimalUtils() {
022        super();
023    }
024
025    private static class DecimalUtilsHolder {
026        static DecimalUtils instance = new DecimalUtils();
027    }
028
029    public static DecimalUtils getInstance() {
030        return DecimalUtilsHolder.instance;
031    }
032
033    /**
034     * 
035     * @param minusSign Character to use when looking for a minus sign in the value, may be null if amount is positive-only
036     * @param fractionSeparator Character that separates the whole part of the value from the decimal portion
037     * @param fractionDigits Number of characters to look for in the decimal portion of the value
038     * @param value Value being parsed
039     */
040    public String parse(String minusSign, String fractionSeparator, Integer fractionDigits, String value) {
041        String result;
042        
043        if(value.equalsIgnoreCase("MAX_VALUE") || value.equalsIgnoreCase("MIN_VALUE")) {
044            result = value;
045        } else {
046            char []rawValue = value.toCharArray();
047            int size = rawValue.length;
048            StringBuilder cleanWhole = new StringBuilder(size);
049            boolean checkMinusSign = minusSign != null;
050            char charMinusSign = checkMinusSign? minusSign.charAt(0): 0;
051            boolean minusSignFound = false;
052            char charFractionSeparator = fractionSeparator == null? '\u0000': fractionSeparator.charAt(0);
053            int intFractionDigits = fractionDigits == null? 0: fractionDigits;
054            StringBuilder cleanFraction = new StringBuilder(intFractionDigits);
055            boolean separatorFound = false;
056            StringBuilder parsedValue = new StringBuilder(size);
057
058            for(int i = 0; i < size; i++) {
059                char testChar = rawValue[i];
060
061                if(testChar >= '\u0030' && testChar <= '\u0039') {
062                    if(separatorFound) {
063                        cleanFraction.append(testChar);
064                        if(cleanFraction.length() == intFractionDigits)
065                            break;
066                    } else {
067                        cleanWhole.append(testChar);
068                    }
069                } else if(testChar == charFractionSeparator) {
070                    separatorFound = true;
071                } else if(checkMinusSign && testChar == charMinusSign) {
072                    minusSignFound = true;
073                }
074            }
075
076            for(int i = cleanFraction.length(); i < intFractionDigits; i++) {
077                cleanFraction.append('0');
078            }
079
080            if(minusSignFound) {
081                parsedValue.append('-');
082            }
083
084            result = parsedValue.append(cleanWhole).append(cleanFraction).toString();
085        }
086        
087        return result;
088    }
089    
090}