← joda-money  /  src/test/java/org/joda/money/format/TestMoneyFormatterBuilder.java

1
/*
2
 *  Copyright 2009-present, 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 static org.assertj.core.api.Assertions.assertThat;
19
import static org.assertj.core.api.AssertionsForClassTypes.assertThatExceptionOfType;
20
21
import java.math.BigDecimal;
22
import java.text.DecimalFormatSymbols;
23
import java.util.Locale;
24
25
import org.joda.money.BigMoney;
26
import org.joda.money.BigMoneyProvider;
27
import org.joda.money.CurrencyUnit;
28
import org.joda.money.Money;
29
import org.junit.jupiter.api.AfterEach;
30
import org.junit.jupiter.api.BeforeEach;
31
import org.junit.jupiter.api.Test;
32
import org.junit.jupiter.params.ParameterizedTest;
33
import org.junit.jupiter.params.provider.MethodSource;
34
35
/**
36
 * Test MoneyFormatterBuilder.
37
 */
38
class TestMoneyFormatterBuilder {
39
40
    private static final CurrencyUnit GBP = CurrencyUnit.GBP;
41
    private static final CurrencyUnit JPY = CurrencyUnit.JPY;
42
    private static final CurrencyUnit BHD = CurrencyUnit.of("BHD");
43
    private static final Money GBP_2_34 = Money.parse("GBP 2.34");
44
    private static final Money GBP_23_45 = Money.parse("GBP 23.45");
45
    private static final Money GBP_234_56 = Money.parse("GBP 234.56");
46
    private static final Money GBP_MINUS_234_56 = Money.parse("GBP -234.56");
47
    private static final Money GBP_2345_67 = Money.parse("GBP 2345.67");
48
    private static final Money GBP_1234567_89 = Money.parse("GBP 1234567.89");
49
    private static final BigMoney GBP_1234_56789 = BigMoney.parse("GBP 1234.56789");
50
    private static final BigMoney GBP_1234567891234_1234567891 = BigMoney.parse("GBP 1234567891234.1234567891");
51
    private static final Money JPY_2345 = Money.parse("JPY 2345");
52
53
    private static final Locale cCachedLocale = Locale.getDefault();
54
    private static final Locale TEST_GB_LOCALE = Locale.of("en", "GB", "TEST");
55
    private static final Locale TEST_FR_LOCALE = Locale.of("fr", "FR", "TEST");
56
    private static final DecimalFormatSymbols FR_SYMBOLS = new DecimalFormatSymbols(Locale.FRANCE);
57
    private static final char FR_DECIMAL = FR_SYMBOLS.getMonetaryDecimalSeparator();
58
    private static final char FR_GROUP = FR_SYMBOLS.getGroupingSeparator();
59
60
    private MoneyFormatterBuilder iBuilder;
61
62
    @BeforeEach
63
    void beforeMethod() {
64
        Locale.setDefault(TEST_GB_LOCALE);
65
        iBuilder = new MoneyFormatterBuilder();
66
    }
67
68
    @AfterEach
69
    void afterMethod() {
70
        Locale.setDefault(cCachedLocale);
71
        iBuilder = null;
72
    }
73
74
    //-----------------------------------------------------------------------
75
    @Test
76
    void test_empty() {
77
        var test = iBuilder.toFormatter();
78
        assertThat(test.print(GBP_2_34)).isEmpty();
79
        assertThat(test).hasToString("");
80
    }
81
82
    //-----------------------------------------------------------------------
83
    @Test
84
    void test_appendCurrencyCode_print() {
85
        iBuilder.appendCurrencyCode();
86
        var test = iBuilder.toFormatter();
87
        assertThat(test.print(GBP_2_34)).isEqualTo("GBP");
88
        assertThat(test).hasToString("${code}");
89
    }
90
91
    @Test
92
    void test_appendCurrencyCode_parse_ok() {
93
        iBuilder.appendCurrencyCode();
94
        var test = iBuilder.toFormatter();
95
        var parsed = test.parse("GBP", 0);
96
        assertThat(parsed.isError()).isFalse();
97
        assertThat(parsed.getIndex()).isEqualTo(3);
98
        assertThat(parsed.getErrorIndex()).isEqualTo(-1);
99
        assertThat(parsed.getAmount()).isNull();
100
        assertThat(parsed.getCurrency()).isEqualTo(CurrencyUnit.GBP);
101
    }
102
103
    @Test
104
    void test_appendCurrencyCode_parse_tooShort() {
105
        iBuilder.appendCurrencyCode();
106
        var test = iBuilder.toFormatter();
107
        var parsed = test.parse("GB", 0);
108
        assertThat(parsed.isError()).isTrue();
109
        assertThat(parsed.getIndex()).isEqualTo(0);
110
        assertThat(parsed.getErrorIndex()).isEqualTo(0);
111
        assertThat(parsed.getAmount()).isNull();
112
        assertThat(parsed.getCurrency()).isNull();
113
    }
114
115
    @Test
116
    void test_appendCurrencyCode_parse_empty() {
117
        iBuilder.appendCurrencyCode();
118
        var test = iBuilder.toFormatter();
119
        var parsed = test.parse("", 0);
120
        assertThat(parsed.isError()).isTrue();
121
        assertThat(parsed.getIndex()).isEqualTo(0);
122
        assertThat(parsed.getErrorIndex()).isEqualTo(0);
123
        assertThat(parsed.getAmount()).isNull();
124
        assertThat(parsed.getCurrency()).isNull();
125
    }
126
127
    //-----------------------------------------------------------------------
128
    @Test
129
    void test_appendCurrencyNumeric3Code_print() {
130
        iBuilder.appendCurrencyNumeric3Code();
131
        var test = iBuilder.toFormatter();
132
        assertThat(test.print(GBP_2_34)).isEqualTo("826");
133
        assertThat(test).hasToString("${numeric3Code}");
134
    }
135
136
    @Test
137
    void test_appendCurrencyNumeric3Code_parse_ok() {
138
        iBuilder.appendCurrencyNumeric3Code();
139
        var test = iBuilder.toFormatter();
140
        var parsed = test.parse("826A", 0);
141
        assertThat(parsed.isError()).isFalse();
142
        assertThat(parsed.getIndex()).isEqualTo(3);
143
        assertThat(parsed.getErrorIndex()).isEqualTo(-1);
144
        assertThat(parsed.getAmount()).isNull();
145
        assertThat(parsed.getCurrency()).isEqualTo(CurrencyUnit.GBP);
146
    }
147
148
    @Test
149
    void test_appendCurrencyNumeric3Code_parse_tooShort() {
150
        iBuilder.appendCurrencyNumeric3Code();
151
        var test = iBuilder.toFormatter();
152
        var parsed = test.parse("82", 0);
153
        assertThat(parsed.isError()).isTrue();
154
        assertThat(parsed.getIndex()).isEqualTo(0);
155
        assertThat(parsed.getErrorIndex()).isEqualTo(0);
156
        assertThat(parsed.getAmount()).isNull();
157
        assertThat(parsed.getCurrency()).isNull();
158
    }
159
160
    @Test
161
    void test_appendCurrencyNumeric3Code_parse_badCurrency() {
162
        iBuilder.appendCurrencyNumeric3Code();
163
        var test = iBuilder.toFormatter();
164
        var parsed = test.parse("991A", 0);
165
        assertThat(parsed.isError()).isTrue();
166
        assertThat(parsed.getIndex()).isEqualTo(0);
167
        assertThat(parsed.getErrorIndex()).isEqualTo(0);
168
        assertThat(parsed.getAmount()).isNull();
169
        assertThat(parsed.getCurrency()).isNull();
170
    }
171
172
    @Test
173
    void test_appendCurrencyNumeric3Code_parse_empty() {
174
        iBuilder.appendCurrencyNumeric3Code();
175
        var test = iBuilder.toFormatter();
176
        var parsed = test.parse("", 0);
177
        assertThat(parsed.isError()).isTrue();
178
        assertThat(parsed.getIndex()).isEqualTo(0);
179
        assertThat(parsed.getErrorIndex()).isEqualTo(0);
180
        assertThat(parsed.getAmount()).isNull();
181
        assertThat(parsed.getCurrency()).isNull();
182
    }
183
184
    //-----------------------------------------------------------------------
185
    @Test
186
    void test_appendCurrencyNumericCode_print() {
187
        iBuilder.appendCurrencyNumericCode();
188
        var test = iBuilder.toFormatter();
189
        assertThat(test.print(GBP_2_34)).isEqualTo("826");
190
        assertThat(test).hasToString("${numericCode}");
191
    }
192
193
    @Test
194
    void test_appendCurrencyNumericCode_parse_ok() {
195
        iBuilder.appendCurrencyNumericCode();
196
        var test = iBuilder.toFormatter();
197
        var parsed = test.parse("826A", 0);
198
        assertThat(parsed.isError()).isFalse();
199
        assertThat(parsed.getIndex()).isEqualTo(3);
200
        assertThat(parsed.getErrorIndex()).isEqualTo(-1);
201
        assertThat(parsed.getAmount()).isNull();
202
        assertThat(parsed.getCurrency()).isEqualTo(CurrencyUnit.GBP);
203
    }
204
205
    @Test
206
    void test_appendCurrencyNumericCode_parse_ok_padded() {
207
        iBuilder.appendCurrencyNumericCode();
208
        var test = iBuilder.toFormatter();
209
        var parsed = test.parse("008A", 0);
210
        assertThat(parsed.isError()).isFalse();
211
        assertThat(parsed.getIndex()).isEqualTo(3);
212
        assertThat(parsed.getErrorIndex()).isEqualTo(-1);
213
        assertThat(parsed.getAmount()).isNull();
214
        assertThat(parsed.getCurrency().getCode()).isEqualTo("ALL");
215
    }
216
217
    @Test
218
    void test_appendCurrencyNumericCode_parse_ok_notPadded1() {
219
        iBuilder.appendCurrencyNumericCode();
220
        var test = iBuilder.toFormatter();
221
        var parsed = test.parse("8A", 0);
222
        assertThat(parsed.isError()).isFalse();
223
        assertThat(parsed.getIndex()).isEqualTo(1);
224
        assertThat(parsed.getErrorIndex()).isEqualTo(-1);
225
        assertThat(parsed.getAmount()).isNull();
226
        assertThat(parsed.getCurrency().getCode()).isEqualTo("ALL");
227
    }
228
229
    @Test
230
    void test_appendCurrencyNumericCode_parse_ok_notPadded2() {
231
        iBuilder.appendCurrencyNumericCode();
232
        var test = iBuilder.toFormatter();
233
        var parsed = test.parse("51 ", 0);
234
        assertThat(parsed.isError()).isFalse();
235
        assertThat(parsed.getIndex()).isEqualTo(2);
236
        assertThat(parsed.getErrorIndex()).isEqualTo(-1);
237
        assertThat(parsed.getAmount()).isNull();
238
        assertThat(parsed.getCurrency().getCode()).isEqualTo("AMD");
239
    }
240
241
    @Test
242
    void test_appendCurrencyNumericCode_parse_tooShort() {
243
        iBuilder.appendCurrencyNumericCode();
244
        var test = iBuilder.toFormatter();
245
        var parsed = test.parse("", 0);
246
        assertThat(parsed.isError()).isTrue();
247
        assertThat(parsed.getIndex()).isEqualTo(0);
248
        assertThat(parsed.getErrorIndex()).isEqualTo(0);
249
        assertThat(parsed.getAmount()).isNull();
250
        assertThat(parsed.getCurrency()).isNull();
251
    }
252
253
    @Test
254
    void test_appendCurrencyNumericCode_parse_badCurrency() {
255
        iBuilder.appendCurrencyNumericCode();
256
        var test = iBuilder.toFormatter();
257
        var parsed = test.parse("991A", 0);
258
        assertThat(parsed.isError()).isTrue();
259
        assertThat(parsed.getIndex()).isEqualTo(0);
260
        assertThat(parsed.getErrorIndex()).isEqualTo(0);
261
        assertThat(parsed.getAmount()).isNull();
262
        assertThat(parsed.getCurrency()).isNull();
263
    }
264
265
    @Test
266
    void test_appendCurrencyNumericCode_parse_empty() {
267
        iBuilder.appendCurrencyNumericCode();
268
        var test = iBuilder.toFormatter();
269
        var parsed = test.parse("", 0);
270
        assertThat(parsed.isError()).isTrue();
271
        assertThat(parsed.getIndex()).isEqualTo(0);
272
        assertThat(parsed.getErrorIndex()).isEqualTo(0);
273
        assertThat(parsed.getAmount()).isNull();
274
        assertThat(parsed.getCurrency()).isNull();
275
    }
276
277
    //-----------------------------------------------------------------------
278
    @Test
279
    void test_appendCurrencySymbolLocalized_print() {
280
        iBuilder.appendCurrencySymbolLocalized();
281
        var test = iBuilder.toFormatter();
282
        assertThat(test.print(GBP_2_34)).isEqualTo("\u00a3");
283
        assertThat(test).hasToString("${symbolLocalized}");
284
    }
285
286
    @Test
287
    void test_appendCurrencySymbolLocalized_parse() {
288
        iBuilder.appendCurrencySymbolLocalized();
289
        var test = iBuilder.toFormatter();
290
        assertThat(test.isParser()).isFalse();
291
    }
292
293
    //-----------------------------------------------------------------------
294
    @Test
295
    void test_appendLiteral_print() {
296
        iBuilder.appendLiteral("Hello");
297
        var test = iBuilder.toFormatter();
298
        assertThat(test.print(GBP_2_34)).isEqualTo("Hello");
299
        assertThat(test).hasToString("'Hello'");
300
    }
301
302
    @Test
303
    void test_appendLiteral_print_empty() {
304
        iBuilder.appendLiteral("");
305
        var test = iBuilder.toFormatter();
306
        assertThat(test.print(GBP_2_34)).isEmpty();
307
        assertThat(test).hasToString("");
308
    }
309
310
    @Test
311
    void test_appendLiteral_print_null() {
312
        iBuilder.appendLiteral((CharSequence) null);
313
        var test = iBuilder.toFormatter();
314
        assertThat(test.print(GBP_2_34)).isEmpty();
315
        assertThat(test).hasToString("");
316
    }
317
318
    @Test
319
    void test_appendLiteral_parse_ok() {
320
        iBuilder.appendLiteral("Hello");
321
        var test = iBuilder.toFormatter();
322
        var parsed = test.parse("HelloWorld", 0);
323
        assertThat(parsed.isError()).isFalse();
324
        assertThat(parsed.getIndex()).isEqualTo(5);
325
        assertThat(parsed.getErrorIndex()).isEqualTo(-1);
326
        assertThat(parsed.getAmount()).isNull();
327
        assertThat(parsed.getCurrency()).isNull();
328
    }
329
330
    @Test
331
    void test_appendLiteral_parse_tooShort() {
332
        iBuilder.appendLiteral("Hello");
333
        var test = iBuilder.toFormatter();
334
        var parsed = test.parse("Hell", 0);
335
        assertThat(parsed.isError()).isTrue();
336
        assertThat(parsed.getIndex()).isEqualTo(0);
337
        assertThat(parsed.getErrorIndex()).isEqualTo(0);
338
        assertThat(parsed.getAmount()).isNull();
339
        assertThat(parsed.getCurrency()).isNull();
340
    }
341
342
    @Test
343
    void test_appendLiteral_parse_noMatch() {
344
        iBuilder.appendLiteral("Hello");
345
        var test = iBuilder.toFormatter();
346
        var parsed = test.parse("Helol", 0);
347
        assertThat(parsed.isError()).isTrue();
348
        assertThat(parsed.getIndex()).isEqualTo(0);
349
        assertThat(parsed.getErrorIndex()).isEqualTo(0);
350
        assertThat(parsed.getAmount()).isNull();
351
        assertThat(parsed.getCurrency()).isNull();
352
    }
353
354
    //-----------------------------------------------------------------------
355
    public static Object[][] data_appendAmount() {
356
        return new Object[][] {
357
            {GBP_2_34, "2.34"},
358
            {GBP_23_45, "23.45"},
359
            {GBP_234_56, "234.56"},
360
            {GBP_2345_67, "2,345.67"},
361
            {GBP_1234567_89, "1,234,567.89"},
362
            {GBP_1234_56789, "1,234.567,89"},
363
            {GBP_1234567891234_1234567891, "1,234,567,891,234.123,456,789,1"},
364
            {GBP_MINUS_234_56, "-234.56"},
365
        };
366
    }
367
368
    @ParameterizedTest
369
    @MethodSource("data_appendAmount")
370
    void test_appendAmount(BigMoneyProvider money, String expected) {
371
        iBuilder.appendAmount();
372
        var test = iBuilder.toFormatter();
373
        assertThat(test.print(money)).isEqualTo(expected);
374
        assertThat(test).hasToString("${amount}");
375
    }
376
377
    @Test
378
    void test_appendAmount_GBP_1234_56789_France() {
379
        iBuilder.appendAmount();
380
        var test = iBuilder.toFormatter(Locale.FRANCE);
381
        assertThat(test.print(GBP_1234_56789)).isEqualTo("1,234.567,89");
382
        assertThat(test).hasToString("${amount}");
383
    }
384
385
    @Test
386
    void test_appendAmount_JPY_2345() {
387
        iBuilder.appendAmount();
388
        var test = iBuilder.toFormatter();
389
        assertThat(test.print(JPY_2345)).isEqualTo("2,345");
390
        assertThat(test).hasToString("${amount}");
391
    }
392
393
    @Test
394
    void test_appendAmount_3dp_BHD() {
395
        iBuilder.appendAmount();
396
        var test = iBuilder.toFormatter();
397
        var money = Money.of(CurrencyUnit.of("BHD"), 6345345.735d);
398
        assertThat(test.print(money)).isEqualTo("6,345,345.735");
399
    }
400
401
    //-----------------------------------------------------------------------
402
    public static Object[][] data_appendAmountLocalized() {
403
        return new Object[][] {
404
            {GBP_2_34, "2" + FR_DECIMAL + "34"},
405
            {GBP_23_45, "23" + FR_DECIMAL + "45"},
406
            {GBP_234_56, "234" + FR_DECIMAL + "56"},
407
            {GBP_2345_67, "2" + FR_GROUP + "345" + FR_DECIMAL + "67"},
408
            {GBP_1234567_89, "1" + FR_GROUP + "234" + FR_GROUP + "567" + FR_DECIMAL + "89"},
409
            {GBP_1234_56789, "1" + FR_GROUP + "234" + FR_DECIMAL + "567" + FR_GROUP + "89"},
410
            {GBP_MINUS_234_56, "-234" + FR_DECIMAL + "56"},
411
        };
412
    }
413
414
    @ParameterizedTest
415
    @MethodSource("data_appendAmountLocalized")
416
    void test_appendAmountLocalized(BigMoneyProvider money, String expected) {
417
        iBuilder.appendAmountLocalized();
418
        var test = iBuilder.toFormatter(Locale.FRANCE);
419
        assertThat(test.print(money)).isEqualTo(expected);
420
        assertThat(test).hasToString("${amount}");
421
    }
422
423
    @Test
424
    void test_appendAmountLocalized_GBP_1234_56789_US() {
425
        iBuilder.appendAmountLocalized();
426
        var test = iBuilder.toFormatter(Locale.US);
427
        assertThat(test.print(GBP_1234_56789)).isEqualTo("1,234.567,89");
428
        assertThat(test).hasToString("${amount}");
429
    }
430
431
    @Test
432
    void test_appendAmountLocalized_JPY_2345() {
433
        iBuilder.appendAmountLocalized();
434
        var test = iBuilder.toFormatter(Locale.FRANCE);
435
        assertThat(test.print(JPY_2345)).isEqualTo("2" + FR_GROUP + "345");
436
        assertThat(test).hasToString("${amount}");
437
    }
438
439
    //-----------------------------------------------------------------------
440
    @Test
441
    void test_appendAmount_MoneyAmountStyle_null() {
442
        assertThatExceptionOfType(NullPointerException.class)
443
            .isThrownBy(() -> iBuilder.appendAmount((MoneyAmountStyle) null));
444
    }
445
446
    public static Object[][] data_appendAmount_MoneyAmountStyle() {
447
        var noGrouping = MoneyAmountStyle.ASCII_DECIMAL_POINT_NO_GROUPING;
448
        var group3Comma = MoneyAmountStyle.ASCII_DECIMAL_POINT_GROUP3_COMMA;
449
        var group3Space = MoneyAmountStyle.ASCII_DECIMAL_POINT_GROUP3_SPACE;
450
        var group3BeforeDp =
451
                MoneyAmountStyle.ASCII_DECIMAL_POINT_GROUP3_COMMA.withGroupingStyle(GroupingStyle.BEFORE_DECIMAL_POINT);
452
        var group3CommaForceDp = MoneyAmountStyle.ASCII_DECIMAL_POINT_GROUP3_COMMA.withForcedDecimalPoint(true);
453
        var group3CommaAbs = MoneyAmountStyle.ASCII_DECIMAL_POINT_GROUP3_COMMA.withAbsValue(true);
454
        var group1Dash = MoneyAmountStyle.ASCII_DECIMAL_POINT_GROUP3_COMMA.withGroupingSize(1).withGroupingCharacter('-');
455
        var group2Dash = MoneyAmountStyle.ASCII_DECIMAL_POINT_GROUP3_COMMA.withGroupingSize(2).withGroupingCharacter('-');
456
        var group4CommaAt = MoneyAmountStyle.ASCII_DECIMAL_POINT_GROUP3_COMMA
457
            .withGroupingSize(4).withDecimalPointCharacter('@').withForcedDecimalPoint(true);
458
        var letters = MoneyAmountStyle.ASCII_DECIMAL_POINT_GROUP3_COMMA.withZeroCharacter('A');
459
        return new Object[][] {
460
            {noGrouping, "2", "2"},
461
            {noGrouping, "2123456", "2123456"},
462
            {noGrouping, "2.34", "2.34"},
463
            {noGrouping, "23.34", "23.34"},
464
            {noGrouping, "234.34", "234.34"},
465
            {noGrouping, "2345.34", "2345.34"},
466
            {noGrouping, "23456.34", "23456.34"},
467
            {noGrouping, "234567.34", "234567.34"},
468
            {noGrouping, "2345678.34", "2345678.34"},
469
            {noGrouping, "2.345", "2.345"},
470
            {noGrouping, "2.3456", "2.3456"},
471
            {noGrouping, "2.34567", "2.34567"},
472
            {noGrouping, "2.345678", "2.345678"},
473
            {noGrouping, "2.3456789", "2.3456789"},
474
475
            {group3Comma, "2", "2"},
476
            {group3Comma, "2123456", "2,123,456"},
477
            {group3Comma, "2.34", "2.34"},
478
            {group3Comma, "23.34", "23.34"},
479
            {group3Comma, "234.34", "234.34"},
480
            {group3Comma, "2345.34", "2,345.34"},
481
            {group3Comma, "23456.34", "23,456.34"},
482
            {group3Comma, "234567.34", "234,567.34"},
483
            {group3Comma, "2345678.34", "2,345,678.34"},
484
            {group3Comma, "2.345", "2.345"},
485
            {group3Comma, "2.3456", "2.345,6"},
486
            {group3Comma, "2.34567", "2.345,67"},
487
            {group3Comma, "2.345678", "2.345,678"},
488
            {group3Comma, "2.3456789", "2.345,678,9"},
489
490
            {group3Space, "2", "2"},
491
            {group3Space, "2123456", "2 123 456"},
492
            {group3Space, "2.34", "2.34"},
493
            {group3Space, "23.34", "23.34"},
494
            {group3Space, "234.34", "234.34"},
495
            {group3Space, "2345.34", "2 345.34"},
496
            {group3Space, "23456.34", "23 456.34"},
497
            {group3Space, "234567.34", "234 567.34"},
498
            {group3Space, "2345678.34", "2 345 678.34"},
499
            {group3Space, "2.345", "2.345"},
500
            {group3Space, "2.3456", "2.345 6"},
501
            {group3Space, "2.34567", "2.345 67"},
502
            {group3Space, "2.345678", "2.345 678"},
503
            {group3Space, "2.3456789", "2.345 678 9"},
504
505
            {group3BeforeDp, "2", "2"},
506
            {group3BeforeDp, "2123456", "2,123,456"},
507
            {group3BeforeDp, "2.34", "2.34"},
508
            {group3BeforeDp, "23.34", "23.34"},
509
            {group3BeforeDp, "234.34", "234.34"},
510
            {group3BeforeDp, "2345.34", "2,345.34"},
511
            {group3BeforeDp, "23456.34", "23,456.34"},
512
            {group3BeforeDp, "234567.34", "234,567.34"},
513
            {group3BeforeDp, "2345678.34", "2,345,678.34"},
514
            {group3BeforeDp, "2.345", "2.345"},
515
            {group3BeforeDp, "2.3456", "2.3456"},
516
            {group3BeforeDp, "2.34567", "2.34567"},
517
            {group3BeforeDp, "2.345678", "2.345678"},
518
            {group3BeforeDp, "2.3456789", "2.3456789"},
519
520
            {group3CommaForceDp, "2", "2."},
521
            {group3CommaForceDp, "2123456", "2,123,456."},
522
            {group3CommaForceDp, "2.34", "2.34"},
523
            {group3CommaForceDp, "23.34", "23.34"},
524
            {group3CommaForceDp, "234.34", "234.34"},
525
            {group3CommaForceDp, "2345.34", "2,345.34"},
526
            {group3CommaForceDp, "23456.34", "23,456.34"},
527
            {group3CommaForceDp, "234567.34", "234,567.34"},
528
            {group3CommaForceDp, "2345678.34", "2,345,678.34"},
529
            {group3CommaForceDp, "2.345", "2.345"},
530
            {group3CommaForceDp, "2.3456", "2.345,6"},
531
            {group3CommaForceDp, "2.34567", "2.345,67"},
532
            {group3CommaForceDp, "2.345678", "2.345,678"},
533
            {group3CommaForceDp, "2.3456789", "2.345,678,9"},
534
535
            {group3CommaAbs, "2", "2"},
536
            {group3CommaAbs, "-2", "2"},
537
            {group3CommaAbs, "2123456", "2,123,456"},
538
            {group3CommaAbs, "-2123456", "2,123,456"},
539
            {group3CommaAbs, "-2.34", "2.34"},
540
            {group3CommaAbs, "-23.34", "23.34"},
541
            {group3CommaAbs, "-234.34", "234.34"},
542
            {group3CommaAbs, "-2345.34", "2,345.34"},
543
            {group3CommaAbs, "-23456.34", "23,456.34"},
544
            {group3CommaAbs, "-234567.34", "234,567.34"},
545
            {group3CommaAbs, "-2345678.34", "2,345,678.34"},
546
            {group3CommaAbs, "-2.345", "2.345"},
547
            {group3CommaAbs, "-2.3456", "2.345,6"},
548
            {group3CommaAbs, "-2.34567", "2.345,67"},
549
            {group3CommaAbs, "-2.345678", "2.345,678"},
550
            {group3CommaAbs, "-2.3456789", "2.345,678,9"},
551
552
            {group1Dash, "2", "2"},
553
            {group1Dash, "2123456", "2-1-2-3-4-5-6"},
554
            {group1Dash, "2.34", "2.3-4"},
555
            {group1Dash, "23.34", "2-3.3-4"},
556
            {group1Dash, "234.34", "2-3-4.3-4"},
557
            {group1Dash, "2345.34", "2-3-4-5.3-4"},
558
            {group1Dash, "23456.34", "2-3-4-5-6.3-4"},
559
            {group1Dash, "234567.34", "2-3-4-5-6-7.3-4"},
560
            {group1Dash, "2345678.34", "2-3-4-5-6-7-8.3-4"},
561
            {group1Dash, "2.345", "2.3-4-5"},
562
            {group1Dash, "2.3456", "2.3-4-5-6"},
563
            {group1Dash, "2.34567", "2.3-4-5-6-7"},
564
            {group1Dash, "2.345678", "2.3-4-5-6-7-8"},
565
            {group1Dash, "2.3456789", "2.3-4-5-6-7-8-9"},
566
567
            {group2Dash, "2", "2"},
568
            {group2Dash, "2123456", "2-12-34-56"},
569
            {group2Dash, "2.34", "2.34"},
570
            {group2Dash, "23.34", "23.34"},
571
            {group2Dash, "234.34", "2-34.34"},
572
            {group2Dash, "2345.34", "23-45.34"},
573
            {group2Dash, "23456.34", "2-34-56.34"},
574
            {group2Dash, "234567.34", "23-45-67.34"},
575
            {group2Dash, "2345678.34", "2-34-56-78.34"},
576
            {group2Dash, "2.345", "2.34-5"},
577
            {group2Dash, "2.3456", "2.34-56"},
578
            {group2Dash, "2.34567", "2.34-56-7"},
579
            {group2Dash, "2.345678", "2.34-56-78"},
580
            {group2Dash, "2.3456789", "2.34-56-78-9"},
581
582
            {group4CommaAt, "2", "2@"},
583
            {group4CommaAt, "2123456", "212,3456@"},
584
            {group4CommaAt, "2.34", "2@34"},
585
            {group4CommaAt, "23.34", "23@34"},
586
            {group4CommaAt, "234.34", "234@34"},
587
            {group4CommaAt, "2345.34", "2345@34"},
588
            {group4CommaAt, "23456.34", "2,3456@34"},
589
            {group4CommaAt, "234567.34", "23,4567@34"},
590
            {group4CommaAt, "2345678.34", "234,5678@34"},
591
            {group4CommaAt, "2.345", "2@345"},
592
            {group4CommaAt, "2.3456", "2@3456"},
593
            {group4CommaAt, "2.34567", "2@3456,7"},
594
            {group4CommaAt, "2.345678", "2@3456,78"},
595
            {group4CommaAt, "2.3456789", "2@3456,789"},
596
597
            {letters, "2", "C"},
598
            {letters, "2123456", "C,BCD,EFG"},
599
            {letters, "2.34", "C.DE"},
600
            {letters, "23.34", "CD.DE"},
601
            {letters, "234.34", "CDE.DE"},
602
            {letters, "2345.34", "C,DEF.DE"},
603
            {letters, "23456.34", "CD,EFG.DE"},
604
            {letters, "234567.34", "CDE,FGH.DE"},
605
            {letters, "2345678.34", "C,DEF,GHI.DE"},
606
            {letters, "2.345", "C.DEF"},
607
            {letters, "2.3456", "C.DEF,G"},
608
            {letters, "2.34567", "C.DEF,GH"},
609
            {letters, "2.345678", "C.DEF,GHI"},
610
            {letters, "2.3456789", "C.DEF,GHI,J"},
611
        };
612
    }
613
614
    @ParameterizedTest
615
    @MethodSource("data_appendAmount_MoneyAmountStyle")
616
    void test_appendAmount_MoneyAmountStyle_GBP(
617
            MoneyAmountStyle style,
618
            String amount,
619
            String expected) {
620
621
        iBuilder.appendAmount(style);
622
        var test = iBuilder.toFormatter();
623
        var money = BigMoney.of(GBP, new BigDecimal(amount));
624
        assertThat(test.print(money)).isEqualTo(expected);
625
        if (!style.isAbsValue()) {
626
            assertThat(test.parse(expected, 0).getAmount()).isEqualTo(money.getAmount());
627
        } else {
628
            assertThat(test.parse(expected, 0).getAmount()).isEqualTo(money.getAmount().abs());
629
        }
630
    }
631
632
    @ParameterizedTest
633
    @MethodSource("data_appendAmount_MoneyAmountStyle")
634
    void test_appendAmount_MoneyAmountStyle_JPY(
635
            MoneyAmountStyle style,
636
            String amount,
637
            String expected) {
638
639
        iBuilder.appendAmount(style);
640
        var test = iBuilder.toFormatter();
641
        var money = BigMoney.of(JPY, new BigDecimal(amount));
642
        assertThat(test.print(money)).isEqualTo(expected);
643
        if (!style.isAbsValue()) {
644
            assertThat(test.parse(expected, 0).getAmount()).isEqualTo(money.getAmount());
645
        } else {
646
            assertThat(test.parse(expected, 0).getAmount()).isEqualTo(money.getAmount().abs());
647
        }
648
    }
649
650
    @ParameterizedTest
651
    @MethodSource("data_appendAmount_MoneyAmountStyle")
652
    void test_appendAmount_MoneyAmountStyle_BHD(
653
            MoneyAmountStyle style,
654
            String amount,
655
            String expected) {
656
657
        iBuilder.appendAmount(style);
658
        var test = iBuilder.toFormatter();
659
        var money = BigMoney.of(BHD, new BigDecimal(amount));
660
        assertThat(test.print(money)).isEqualTo(expected);
661
        if (!style.isAbsValue()) {
662
            assertThat(test.parse(expected, 0).getAmount()).isEqualTo(money.getAmount());
663
        } else {
664
            assertThat(test.parse(expected, 0).getAmount()).isEqualTo(money.getAmount().abs());
665
        }
666
    }
667
668
    @Test
669
    void test_appendAmount_MoneyAmountStyle_JPY_issue49() {
670
        var money = Money.parse("JPY 12");
671
        var style = MoneyAmountStyle.LOCALIZED_GROUPING;
672
        var formatter = new MoneyFormatterBuilder()
673
            .appendAmount(style)
674
            .toFormatter()
675
            .withLocale(Locale.JAPAN);
676
        assertThat(formatter.print(money)).isEqualTo("12");
677
    }
678
679
    //-----------------------------------------------------------------------
680
    public static Object[][] data_appendAmountExtendedGrouping() {
681
        return new Object[][] {
682
            {GBP_2_34, "2.34"},
683
            {GBP_23_45, "23.45"},
684
            {GBP_234_56, "234.56"},
685
            {GBP_2345_67, "2,345.67"},
686
            {GBP_1234567_89, "12,34,567.89"},
687
            {GBP_1234_56789, "1,234.567,89"},
688
            {GBP_1234567891234_1234567891, "12,34,56,78,91,234.123,45,67,89,1"},
689
            {GBP_MINUS_234_56, "-234.56"},
690
        };
691
    }
692
693
    @ParameterizedTest
694
    @MethodSource("data_appendAmountExtendedGrouping")
695
    void test_appendAmount_parseExtendedGroupingSize(BigMoneyProvider money, String expected) {
696
        iBuilder.appendAmount();
697
        var test = new MoneyFormatterBuilder()
698
            .appendAmount(MoneyAmountStyle.ASCII_DECIMAL_POINT_GROUP3_COMMA.withExtendedGroupingSize(2))
699
            .toFormatter();
700
        assertThat(test.print(money)).isEqualTo(expected);
701
        assertThat(test).hasToString("${amount}");
702
    }
703
704
    //-----------------------------------------------------------------------
705
    @Test
706
    void test_appendAmount_parseExcessGrouping() {
707
        var expected = BigMoney.parse("GBP 12123.4567");
708
        var f = new MoneyFormatterBuilder()
709
            .appendCurrencyCode()
710
            .appendLiteral(" ")
711
            .appendAmount(MoneyAmountStyle.ASCII_DECIMAL_POINT_GROUP3_COMMA)
712
            .toFormatter();
713
        var money = f.parseBigMoney("GBP 12,1,2,3,.,45,6,7");
714
        assertThat(money).isEqualTo(expected);
715
    }
716
717
    //-----------------------------------------------------------------------
718
    @Test
719
    void test_append_MoneyPrinterMoneyParser_printer() {
720
        MoneyPrinter printer = (context, appendable, money) -> appendable.append("HELLO");
721
        iBuilder.append(printer, null);
722
        var test = iBuilder.toFormatter();
723
        assertThat(test.isPrinter()).isTrue();
724
        assertThat(test.isParser()).isFalse();
725
        assertThat(test.print(JPY_2345)).isEqualTo("HELLO");
726
        assertThat(test.toString()).startsWith("org.joda.money.format.TestMoneyFormatterBuilder$");
727
    }
728
729
    @Test
730
    void test_append_MoneyPrinterMoneyParser_parser() {
731
        MoneyParser parser = (context) -> {
732
            context.setAmount(JPY_2345.getAmount());
733
            context.setCurrency(JPY_2345.getCurrencyUnit());
734
        };
735
        iBuilder.append(null, parser);
736
        var test = iBuilder.toFormatter();
737
        assertThat(test.isPrinter()).isFalse();
738
        assertThat(test.isParser()).isTrue();
739
        assertThat(test.parseMoney("")).isEqualTo(JPY_2345);
740
        assertThat(test.toString()).startsWith("org.joda.money.format.TestMoneyFormatterBuilder$");
741
    }
742
743
    @Test
744
    void test_append_MoneyPrinter_nullMoneyPrinter_nullMoneyParser() {
745
        iBuilder.append((MoneyPrinter) null, (MoneyParser) null);
746
        var test = iBuilder.toFormatter();
747
        assertThat(test.isPrinter()).isFalse();
748
        assertThat(test.isParser()).isFalse();
749
        assertThat(test).hasToString("");
750
    }
751
752
    //-----------------------------------------------------------------------
753
    @Test
754
    void test_append_MoneyFormatter() {
755
        var f1 = new MoneyFormatterBuilder().appendAmount().toFormatter();
756
        var f2 = new MoneyFormatterBuilder().appendCurrencyCode().appendLiteral(" ").append(f1).toFormatter();
757
        assertThat(f2.print(GBP_2345_67)).isEqualTo("GBP 2,345.67");
758
    }
759
760
    //-----------------------------------------------------------------------
761
    @Test
762
    void test_appendSigned_PN() {
763
        var pos = new MoneyFormatterBuilder()
764
            .appendCurrencyCode()
765
            .appendLiteral(" ")
766
            .appendAmount()
767
            .toFormatter();
768
        var neg = new MoneyFormatterBuilder()
769
            .appendLiteral("(")
770
            .appendCurrencyCode()
771
            .appendLiteral(" ")
772
            .appendAmount(MoneyAmountStyle.ASCII_DECIMAL_POINT_GROUP3_COMMA.withAbsValue(true))
773
            .appendLiteral(")")
774
            .toFormatter();
775
        var f = new MoneyFormatterBuilder().appendSigned(pos, neg).toFormatter();
776
        assertThat(f)
777
            .hasToString("PositiveZeroNegative(${code}' '${amount},${code}' '${amount},'('${code}' '${amount}')')");
778
        assertThat(f.print(GBP_234_56)).isEqualTo("GBP 234.56");
779
        assertThat(f.print(Money.zero(GBP))).isEqualTo("GBP 0.00");
780
        assertThat(f.print(GBP_MINUS_234_56)).isEqualTo("(GBP 234.56)");
781
        assertThat(f.parseMoney("GBP 234.56")).isEqualTo(GBP_234_56);
782
        assertThat(f.parseMoney("GBP 0")).isEqualTo(Money.zero(GBP));
783
        assertThat(f.parseMoney("(GBP 234.56)")).isEqualTo(GBP_MINUS_234_56);
784
        var context = f.parse("X", 0);
785
        assertThat(context.getIndex()).isEqualTo(0);
786
        assertThat(context.getErrorIndex()).isEqualTo(0);
787
    }
788
789
    //-----------------------------------------------------------------------
790
    @Test
791
    void test_appendSigned_PZN() {
792
        var pos = new MoneyFormatterBuilder()
793
            .appendCurrencyCode()
794
            .appendLiteral(" ")
795
            .appendAmount()
796
            .toFormatter();
797
        var zro = new MoneyFormatterBuilder()
798
            .appendCurrencyCode()
799
            .appendLiteral(" -")
800
            .toFormatter();
801
        var neg = new MoneyFormatterBuilder()
802
            .appendLiteral("(")
803
            .appendCurrencyCode()
804
            .appendLiteral(" ")
805
            .appendAmount(MoneyAmountStyle.ASCII_DECIMAL_POINT_GROUP3_COMMA.withAbsValue(true))
806
            .appendLiteral(")")
807
            .toFormatter();
808
        var f = new MoneyFormatterBuilder().appendSigned(pos, zro, neg).toFormatter();
809
        assertThat(f.print(GBP_234_56)).isEqualTo("GBP 234.56");
810
        assertThat(f.print(Money.zero(GBP))).isEqualTo("GBP -");
811
        assertThat(f.print(GBP_MINUS_234_56)).isEqualTo("(GBP 234.56)");
812
        assertThat(f.parseMoney("GBP 234.56")).isEqualTo(GBP_234_56);
813
        assertThat(f.parseMoney("GBP -234.56")).isEqualTo(GBP_MINUS_234_56);
814
        assertThat(f.parseMoney("GBP -")).isEqualTo(Money.zero(GBP));
815
        assertThat(f.parseMoney("(GBP 234.56)")).isEqualTo(GBP_MINUS_234_56);
816
        assertThat(f.parseMoney("(GBP -234.56)")).isEqualTo(GBP_MINUS_234_56);
817
    }
818
819
    @Test
820
    void test_appendSigned_PZN_edgeCases() {
821
        var pos = new MoneyFormatterBuilder()
822
            .appendAmount()
823
            .toFormatter();
824
        var zro = new MoneyFormatterBuilder()
825
            .appendAmount()
826
            .appendLiteral(" (zero)")
827
            .toFormatter();
828
        var neg = new MoneyFormatterBuilder()
829
            .appendLiteral("(")
830
            .appendAmount(MoneyAmountStyle.ASCII_DECIMAL_POINT_GROUP3_COMMA.withAbsValue(true))
831
            .appendLiteral(")")
832
            .toFormatter();
833
        var f = new MoneyFormatterBuilder()
834
            .appendCurrencyCode().appendLiteral(" ").appendSigned(pos, zro, neg).toFormatter();
835
        assertThat(f.print(GBP_234_56)).isEqualTo("GBP 234.56");
836
        assertThat(f.print(BigMoney.zero(GBP).withScale(2))).isEqualTo("GBP 0.00 (zero)");
837
        assertThat(f.print(GBP_MINUS_234_56)).isEqualTo("GBP (234.56)");
838
        assertThat(f.parseBigMoney("GBP 234.56")).isEqualTo(GBP_234_56.toBigMoney());
839
        assertThat(f.parseBigMoney("GBP 0.00 (zero)")).isEqualTo(BigMoney.zero(GBP).withScale(2));
840
        assertThat(f.parseBigMoney("GBP 1.23 (zero)")).isEqualTo(BigMoney.zero(GBP));
841
        assertThat(f.parseBigMoney("GBP (234.56)")).isEqualTo(GBP_MINUS_234_56.toBigMoney());
842
    }
843
844
    //-----------------------------------------------------------------------
845
    @Test
846
    void test_toFormatter_defaultLocale() {
847
        var test = iBuilder.toFormatter();
848
        assertThat(test.getLocale()).isEqualTo(TEST_GB_LOCALE);
849
    }
850
851
    @Test
852
    void test_toFormatter_Locale() {
853
        var test = iBuilder.toFormatter(TEST_FR_LOCALE);
854
        assertThat(test.getLocale()).isEqualTo(TEST_FR_LOCALE);
855
    }
856
857
}
858