1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
27
28
29
30 final class AmountPrinterParser implements MoneyPrinter, MoneyParser, Serializable {
31
32
33 private static final long serialVersionUID = 1L;
34
35
36 private final MoneyAmountStyle style;
37
38
39
40
41
42 AmountPrinterParser(MoneyAmountStyle style) {
43 this.style = style;
44 }
45
46
47 public void print(MoneyPrintContext context, Appendable appendable, BigMoney money) throws IOException {
48 MoneyAmountStyle activeStyle = style.localize(context.getLocale());
49 if (MoneyUtils.isNegative(money)) {
50 money = money.negated();
51 appendable.append(activeStyle.getNegativeSignCharacter());
52 }
53 String str = money.getAmount().toPlainString();
54 char zeroChar = activeStyle.getZeroCharacter();
55 if (zeroChar != '0') {
56 int diff = zeroChar - '0';
57 StringBuilder zeroConvert = new StringBuilder(str);
58 for (int i = 0; i < str.length(); i++) {
59 char ch = str.charAt(i);
60 if (ch >= '0' && ch <= '9') {
61 zeroConvert.setCharAt(i, (char) (ch + diff));
62 }
63 }
64 str = zeroConvert.toString();
65 }
66 final int decPoint = str.indexOf('.');
67 final int afterDecPoint = decPoint + 1;;
68 if (activeStyle.getGroupingStyle() == GroupingStyle.NONE) {
69 if (decPoint < 0) {
70 appendable.append(str);
71 if (activeStyle.isForcedDecimalPoint()) {
72 appendable.append(activeStyle.getDecimalPointCharacter());
73 }
74 } else {
75 appendable.append(str.subSequence(0, decPoint))
76 .append(activeStyle.getDecimalPointCharacter()).append(str.substring(afterDecPoint));
77 }
78 } else {
79 int groupingSize = activeStyle.getGroupingSize();
80 char groupingChar = activeStyle.getGroupingCharacter();
81 int pre = (decPoint < 0 ? str.length() : decPoint);
82 int post = (decPoint < 0 ? 0 : str.length() - decPoint - 1);
83 for (int i = 0; pre > 0; i++, pre--) {
84 appendable.append(str.charAt(i));
85 if (pre > 3 && pre % groupingSize == 1) {
86 appendable.append(groupingChar);
87 }
88 }
89 if (decPoint >= 0 || activeStyle.isForcedDecimalPoint()) {
90 appendable.append(activeStyle.getDecimalPointCharacter());
91 }
92 if (activeStyle.getGroupingStyle() == GroupingStyle.BEFORE_DECIMAL_POINT) {
93 appendable.append(str.substring(afterDecPoint));
94 } else {
95 for (int i = 0; i < post; i++) {
96 appendable.append(str.charAt(i + afterDecPoint));
97 if (i % groupingSize == 2) {
98 appendable.append(groupingChar);
99 }
100 }
101 }
102 }
103 }
104
105 public void parse(MoneyParseContext context) {
106 final int len = context.getTextLength();
107 final MoneyAmountStyle activeStyle = style.localize(context.getLocale());
108 char[] buf = new char[len - context.getIndex()];
109 int bufPos = 0;
110 boolean dpSeen = false;
111 boolean lastWasGroup = false;
112 int pos = context.getIndex();
113 if (pos < len) {
114 char ch = context.getText().charAt(pos++);
115 if (ch == activeStyle.getNegativeSignCharacter()) {
116 buf[bufPos++] = '-';
117 } else if (ch == activeStyle.getPositiveSignCharacter()) {
118 buf[bufPos++] = '+';
119 } else if (ch >= activeStyle.getZeroCharacter() && ch < activeStyle.getZeroCharacter() + 10) {
120 buf[bufPos++] = (char) ('0' + ch - activeStyle.getZeroCharacter());
121 } else if (ch == activeStyle.getDecimalPointCharacter()) {
122 buf[bufPos++] = '.';
123 dpSeen = true;
124 } else {
125 context.setError();
126 return;
127 }
128 }
129 for ( ; pos < len; pos++) {
130 char ch = context.getText().charAt(pos);
131 if (ch >= activeStyle.getZeroCharacter() && ch < activeStyle.getZeroCharacter() + 10) {
132 buf[bufPos++] = (char) ('0' + ch - activeStyle.getZeroCharacter());
133 lastWasGroup = false;
134 } else if (ch == activeStyle.getDecimalPointCharacter() && dpSeen == false) {
135 buf[bufPos++] = '.';
136 dpSeen = true;
137 lastWasGroup = false;
138 } else if (ch == activeStyle.getGroupingCharacter() && lastWasGroup == false) {
139 lastWasGroup = true;
140 } else {
141 break;
142 }
143 }
144 if (lastWasGroup) {
145 pos--;
146 }
147 try {
148 context.setAmount(new BigDecimal(buf, 0, bufPos));
149 context.setIndex(pos);
150 } catch (NumberFormatException ex) {
151 context.setError();
152 }
153 }
154
155 @Override
156 public String toString() {
157 return "${amount}";
158 }
159
160 }