Coverage Report - org.joda.money.format.AmountPrinterParser
 
Classes in this File Line Coverage Branch Coverage Complexity
AmountPrinterParser
97%
80/82
96%
62/64
9.5
 
 1  
 /*
 2  
  *  Copyright 2009-2013 Stephen Colebourne
 3  
  *
 4  
  *  Licensed under the Apache License, Version 2.0 (the "License");
 5  
  *  you may not use this file except in compliance with the License.
 6  
  *  You may obtain a copy of the License at
 7  
  *
 8  
  *      http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 10  
  *  Unless required by applicable law or agreed to in writing, software
 11  
  *  distributed under the License is distributed on an "AS IS" BASIS,
 12  
  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  *  See the License for the specific language governing permissions and
 14  
  *  limitations under the License.
 15  
  */
 16  
 package org.joda.money.format;
 17  
 
 18  
 import java.io.IOException;
 19  
 import java.io.Serializable;
 20  
 import java.math.BigDecimal;
 21  
 
 22  
 import org.joda.money.BigMoney;
 23  
 import org.joda.money.MoneyUtils;
 24  
 
 25  
 /**
 26  
  * Prints and parses the amount part of the money.
 27  
  * <p>
 28  
  * This class is immutable and thread-safe.
 29  
  */
 30  
 final class AmountPrinterParser implements MoneyPrinter, MoneyParser, Serializable {
 31  
 
 32  
     /** Serialization version. */
 33  
     private static final long serialVersionUID = 1L;
 34  
 
 35  
     /** The style to use. */
 36  
     private final MoneyAmountStyle style;
 37  
 
 38  
     /**
 39  
      * Constructor.
 40  
      * @param style  the style, not null
 41  
      */
 42  105
     AmountPrinterParser(MoneyAmountStyle style) {
 43  105
         this.style = style;
 44  105
     }
 45  
 
 46  
     //-----------------------------------------------------------------------
 47  
     public void print(MoneyPrintContext context, Appendable appendable, BigMoney money) throws IOException {
 48  37
         MoneyAmountStyle activeStyle = style.localize(context.getLocale());
 49  37
         if (MoneyUtils.isNegative(money)) {
 50  1
             money = money.negated();
 51  1
             appendable.append(activeStyle.getNegativeSignCharacter());
 52  
         }
 53  37
         String str = money.getAmount().toPlainString();
 54  37
         char zeroChar = activeStyle.getZeroCharacter();
 55  37
         if (zeroChar != '0') {
 56  2
             int diff = zeroChar - '0';
 57  2
             StringBuilder zeroConvert = new StringBuilder(str);
 58  14
             for (int i = 0; i < str.length(); i++) {
 59  12
                 char ch = str.charAt(i);
 60  12
                 if (ch >= '0' && ch <= '9') {
 61  10
                     zeroConvert.setCharAt(i, (char) (ch + diff));
 62  
                 }
 63  
             }
 64  2
             str = zeroConvert.toString();
 65  
         }
 66  37
         final int decPoint = str.indexOf('.');
 67  37
         final int afterDecPoint = decPoint + 1;;
 68  37
         if (activeStyle.getGroupingStyle() == GroupingStyle.NONE) {
 69  11
             if (decPoint < 0) {
 70  2
                 appendable.append(str);
 71  2
                 if (activeStyle.isForcedDecimalPoint()) {
 72  1
                     appendable.append(activeStyle.getDecimalPointCharacter());
 73  
                 }
 74  
             } else {
 75  9
                 appendable.append(str.subSequence(0, decPoint))
 76  
                     .append(activeStyle.getDecimalPointCharacter()).append(str.substring(afterDecPoint));
 77  
             }
 78  
         } else {
 79  26
             int groupingSize = activeStyle.getGroupingSize();
 80  26
             char groupingChar = activeStyle.getGroupingCharacter();
 81  26
             int pre = (decPoint < 0 ? str.length() : decPoint);
 82  26
             int post = (decPoint < 0 ? 0 : str.length() - decPoint - 1);
 83  145
             for (int i = 0; pre > 0; i++, pre--) {
 84  119
                 appendable.append(str.charAt(i));
 85  119
                 if (pre > 3 && pre % groupingSize == 1) {
 86  26
                     appendable.append(groupingChar);
 87  
                 }
 88  
             }
 89  26
             if (decPoint >= 0 || activeStyle.isForcedDecimalPoint()) {
 90  24
                 appendable.append(activeStyle.getDecimalPointCharacter());
 91  
             }
 92  26
             if (activeStyle.getGroupingStyle() == GroupingStyle.BEFORE_DECIMAL_POINT) {
 93  1
                 appendable.append(str.substring(afterDecPoint));
 94  
             } else {
 95  111
                 for (int i = 0; i < post; i++) {
 96  86
                     appendable.append(str.charAt(i + afterDecPoint));
 97  86
                     if (i % groupingSize == 2) {
 98  14
                         appendable.append(groupingChar);
 99  
                     }
 100  
                 }
 101  
             }
 102  
         }
 103  37
     }
 104  
 
 105  
     public void parse(MoneyParseContext context) {
 106  34
         final int len = context.getTextLength();
 107  34
         final MoneyAmountStyle activeStyle = style.localize(context.getLocale());
 108  34
         char[] buf = new char[len - context.getIndex()];
 109  34
         int bufPos = 0;
 110  34
         boolean dpSeen = false;
 111  34
         boolean lastWasGroup = false;
 112  34
         int pos = context.getIndex();
 113  34
         if (pos < len) {
 114  34
             char ch = context.getText().charAt(pos++);
 115  34
             if (ch == activeStyle.getNegativeSignCharacter()) {
 116  1
                 buf[bufPos++] = '-';
 117  33
             } else if (ch == activeStyle.getPositiveSignCharacter()) {
 118  1
                 buf[bufPos++] = '+';
 119  32
             } else if (ch >= activeStyle.getZeroCharacter() && ch < activeStyle.getZeroCharacter() + 10) {
 120  25
                 buf[bufPos++] = (char) ('0' + ch - activeStyle.getZeroCharacter());
 121  7
             } else if (ch == activeStyle.getDecimalPointCharacter()) {
 122  1
                 buf[bufPos++] = '.';
 123  1
                 dpSeen = true;
 124  
             } else {
 125  6
                 context.setError();
 126  6
                 return;
 127  
             }
 128  
         }
 129  236
         for ( ; pos < len; pos++) {
 130  130
             char ch = context.getText().charAt(pos);
 131  130
             if (ch >= activeStyle.getZeroCharacter() && ch < activeStyle.getZeroCharacter() + 10) {
 132  73
                 buf[bufPos++] = (char) ('0' + ch - activeStyle.getZeroCharacter());
 133  73
                 lastWasGroup = false;
 134  57
             } else if (ch == activeStyle.getDecimalPointCharacter() && dpSeen == false) {
 135  23
                 buf[bufPos++] = '.';
 136  23
                 dpSeen = true;
 137  23
                 lastWasGroup = false;
 138  34
             } else if (ch == activeStyle.getGroupingCharacter() && lastWasGroup == false) {
 139  8
                 lastWasGroup = true;
 140  
             } else {
 141  
                 break;
 142  
             }
 143  
         }
 144  28
         if (lastWasGroup) {
 145  3
             pos--;
 146  
         }
 147  
         try {
 148  28
             context.setAmount(new BigDecimal(buf, 0, bufPos));
 149  28
             context.setIndex(pos);
 150  0
         } catch (NumberFormatException ex) {
 151  0
             context.setError();
 152  28
         }
 153  28
     }
 154  
 
 155  
     @Override
 156  
     public String toString() {
 157  52
         return "${amount}";
 158  
     }
 159  
 
 160  
 }