• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

javadev / moneytostr-russian / #388

19 Apr 2024 03:36AM UTC coverage: 75.333% (+0.1%) from 75.223%
#388

push

web-flow
Added language POL and currency PLZ

339 of 450 relevant lines covered (75.33%)

0.75 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

75.33
src/main/java/com/github/moneytostr/MoneyToStr.java
1
/*
2
 * $Id$
3
 *
4
 * Copyright 2014 Valentyn Kolesnikov
5
 *
6
 * Licensed under the Apache License, Version 2.0 (the "License");
7
 * you may not use this file except in compliance with the License.
8
 * You may obtain a copy of the License at
9
 *
10
 *     http://www.apache.org/licenses/LICENSE-2.0
11
 *
12
 * Unless required by applicable law or agreed to in writing, software
13
 * distributed under the License is distributed on an "AS IS" BASIS,
14
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
 * See the License for the specific language governing permissions and
16
 * limitations under the License.
17
 */
18
package com.github.moneytostr;
19

20
import java.math.BigDecimal;
21
import java.util.ArrayList;
22
import java.util.LinkedHashMap;
23
import java.util.List;
24
import java.util.Map;
25

26
/**
27
 * Converts numbers to symbols.
28
 *
29
 * @author Valentyn Kolesnikov
30
 * @version $Revision$ $Date$
31
 */
32
public class MoneyToStr {
33
    private static final int INDEX_3 = 3;
34
    private static final int INDEX_2 = 2;
35
    private static final int INDEX_1 = 1;
36
    private static final int INDEX_0 = 0;
37
    private static Map<String, Object> jsonMap;
38
    private static final int NUM0 = 0;
39
    private static final int NUM1 = 1;
40
    private static final int NUM2 = 2;
41
    private static final int NUM3 = 3;
42
    private static final int NUM4 = 4;
43
    private static final int NUM5 = 5;
44
    private static final int NUM6 = 6;
45
    private static final int NUM7 = 7;
46
    private static final int NUM8 = 8;
47
    private static final int NUM9 = 9;
48
    private static final int NUM10 = 10;
49
    private static final int NUM11 = 11;
50
    private static final int NUM14 = 14;
51
    private static final int NUM100 = 100;
52
    private static final int NUM1000 = 1000;
53
    private static final int NUM10000 = 10000;
54
    private static final String CURRENCY_LIST =
55
            "{\n"
56
                    + "  \"CurrencyList\": {\n"
57
                    + "    \"language\": {\n"
58
                    + "      \"-value\": \"UKR\"\n"
59
                    + "    },\n"
60
                    + "    \"UKR\": {\n"
61
                    + "      \"item\": [\n"
62
                    + "        {\n"
63
                    + "          \"-value\": \"minus\",\n"
64
                    + "          \"-text\": \"мінус\"\n"
65
                    + "        },\n"
66
                    + "        {\n"
67
                    + "          \"-value\": \"0\",\n"
68
                    + "          \"-text\": \"нуль\"\n"
69
                    + "        },\n"
70
                    + "        {\n"
71
                    + "          \"-value\": \"1000_10\",\n"
72
                    + "          \"-text\": \"тисяч,мільйонів,мільярдів,трильйонів\"\n"
73
                    + "        },\n"
74
                    + "        {\n"
75
                    + "          \"-value\": \"1000_1\",\n"
76
                    + "          \"-text\": \"тисяча,мільйон,мільярд,трильйон\"\n"
77
                    + "        },\n"
78
                    + "        {\n"
79
                    + "          \"-value\": \"1000_234\",\n"
80
                    + "          \"-text\": \"тисячі,мільйона,мільярда,трильйона\"\n"
81
                    + "        },\n"
82
                    + "        {\n"
83
                    + "          \"-value\": \"1000_5\",\n"
84
                    + "          \"-text\": \"тисяч,мільйонів,мільярдів,трильйонів\"\n"
85
                    + "        },\n"
86
                    + "        {\n"
87
                    + "          \"-value\": \"10_19\",\n"
88
                    + "          \"-text\": \"десять,одинадцять,дванадцять,тринадцять,чотирнадцять,п'ятнадцять,шістнадцять,сімнадцять,вісімнадцять,дев'ятнадцять\"\n"
89
                    + "        },\n"
90
                    + "        {\n"
91
                    + "          \"-value\": \"1\",\n"
92
                    + "          \"-text\": \"одна,один,один,одна\"\n"
93
                    + "        },\n"
94
                    + "        {\n"
95
                    + "          \"-value\": \"2\",\n"
96
                    + "          \"-text\": \"дві,два,два,дві\"\n"
97
                    + "        },\n"
98
                    + "        {\n"
99
                    + "          \"-value\": \"3_9\",\n"
100
                    + "          \"-text\": \"три,чотири,п'ять,шість,сім,вісім,дев'ять\"\n"
101
                    + "        },\n"
102
                    + "        {\n"
103
                    + "          \"-value\": \"100_900\",\n"
104
                    + "          \"-text\": \"сто ,двісті ,триста ,чотириста ,п'ятсот ,шістсот ,сімсот ,вісімсот ,дев'ятсот \"\n"
105
                    + "        },\n"
106
                    + "        {\n"
107
                    + "          \"-value\": \"20_90\",\n"
108
                    + "          \"-text\": \"двадцять ,тридцять ,сорок ,п'ятдесят ,шістдесят ,сімдесят ,вісімдесят ,дев'яносто \"\n"
109
                    + "        },\n"
110
                    + "        {\n"
111
                    + "          \"-value\": \"pdv\",\n"
112
                    + "          \"-text\": \"в т.ч. ПДВ \"\n"
113
                    + "        },\n"
114
                    + "        {\n"
115
                    + "          \"-value\": \"pdv_value\",\n"
116
                    + "          \"-text\": \"20\"\n"
117
                    + "        }\n"
118
                    + "      ]\n"
119
                    + "    },\n"
120
                    + "    \"POL\": {\n"
121
                    + "      \"item\": [\n"
122
                    + "        {\n"
123
                    + "          \"-value\": \"minus\",\n"
124
                    + "          \"-text\": \"minus\"\n"
125
                    + "        },\n"
126
                    + "        {\n"
127
                    + "          \"-value\": \"0\",\n"
128
                    + "          \"-text\": \"zero\"\n"
129
                    + "        },\n"
130
                    + "        {\n"
131
                    + "          \"-value\": \"1000_10\",\n"
132
                    + "          \"-text\": \"tysięcy,milionów,miliardów,trilionów\"\n"
133
                    + "        },\n"
134
                    + "        {\n"
135
                    + "          \"-value\": \"1000_1\",\n"
136
                    + "          \"-text\": \"tysiąc,milion,miliard,trylion\"\n"
137
                    + "        },\n"
138
                    + "        {\n"
139
                    + "          \"-value\": \"1000_234\",\n"
140
                    + "          \"-text\": \"tysiące,miliony,miliardy,tryliony\"\n"
141
                    + "        },\n"
142
                    + "        {\n"
143
                    + "          \"-value\": \"1000_5\",\n"
144
                    + "          \"-text\": \"tysięcy,milionów,miliardów,trylionów\"\n"
145
                    + "        },\n"
146
                    + "        {\n"
147
                    + "          \"-value\": \"10_19\",\n"
148
                    + "          \"-text\": \"dziesięć,jedenaście,dwanaście,trzynaście,czternaście,piętnaście,szesnaście,siedemnaście,osiemnaście,dziewiętnaście\"\n"
149
                    + "        },\n"
150
                    + "        {\n"
151
                    + "          \"-value\": \"1\",\n"
152
                    + "          \"-text\": \"jeden,jeden,jeden,jeden\"\n"
153
                    + "        },\n"
154
                    + "        {\n"
155
                    + "          \"-value\": \"2\",\n"
156
                    + "          \"-text\": \"dwie,dwa,dwa,dwie\"\n"
157
                    + "        },\n"
158
                    + "        {\n"
159
                    + "          \"-value\": \"3_9\",\n"
160
                    + "          \"-text\": \"trzy,cztery,pięć,sześć,siedem,osiem,dziewięć\"\n"
161
                    + "        },\n"
162
                    + "        {\n"
163
                    + "          \"-value\": \"100_900\",\n"
164
                    + "          \"-text\": \"sto ,dwieście ,trzysta ,czterysta ,pięćset ,sześćset ,siedemset ,osiemset ,dziewięćset \"\n"
165
                    + "        },\n"
166
                    + "        {\n"
167
                    + "          \"-value\": \"20_90\",\n"
168
                    + "          \"-text\": \"dwadzieścia ,trzydzieści ,czterdzieści ,pięćdziesiąt ,sześćdziesiąt ,siedemdziesiąt ,osiemdziesiąt ,dziewięćdziesiąt \"\n"
169
                    + "        },\n"
170
                    + "        {\n"
171
                    + "          \"-value\": \"pdv\",\n"
172
                    + "          \"-text\": \"в т.ч. ПДВ \"\n"
173
                    + "        },\n"
174
                    + "        {\n"
175
                    + "          \"-value\": \"pdv_value\",\n"
176
                    + "          \"-text\": \"20\"\n"
177
                    + "        }\n"
178
                    + "      ]\n"
179
                    + "    },\n"
180
                    + "    \"RUS\": {\n"
181
                    + "      \"item\": [\n"
182
                    + "        {\n"
183
                    + "          \"-value\": \"minus\",\n"
184
                    + "          \"-text\": \"минус\"\n"
185
                    + "        },\n"
186
                    + "        {\n"
187
                    + "          \"-value\": \"0\",\n"
188
                    + "          \"-text\": \"ноль\"\n"
189
                    + "        },\n"
190
                    + "        {\n"
191
                    + "          \"-value\": \"1000_10\",\n"
192
                    + "          \"-text\": \"тысяч,миллионов,миллиардов,триллионов\"\n"
193
                    + "        },\n"
194
                    + "        {\n"
195
                    + "          \"-value\": \"1000_1\",\n"
196
                    + "          \"-text\": \"тысяча,миллион,миллиард,триллион\"\n"
197
                    + "        },\n"
198
                    + "        {\n"
199
                    + "          \"-value\": \"1000_234\",\n"
200
                    + "          \"-text\": \"тысячи,миллиона,миллиарда,триллиона\"\n"
201
                    + "        },\n"
202
                    + "        {\n"
203
                    + "          \"-value\": \"1000_5\",\n"
204
                    + "          \"-text\": \"тысяч,миллионов,миллиардов,триллионов\"\n"
205
                    + "        },\n"
206
                    + "        {\n"
207
                    + "          \"-value\": \"10_19\",\n"
208
                    + "          \"-text\": \"десять,одиннадцать,двенадцать,тринадцать,четырнадцать,пятнадцать,шестнадцать,семнадцать,восемнадцать,девятнадцать\"\n"
209
                    + "        },\n"
210
                    + "        {\n"
211
                    + "          \"-value\": \"1\",\n"
212
                    + "          \"-text\": \"одна,один,один,одна\"\n"
213
                    + "        },\n"
214
                    + "        {\n"
215
                    + "          \"-value\": \"2\",\n"
216
                    + "          \"-text\": \"две,два,два,две\"\n"
217
                    + "        },\n"
218
                    + "        {\n"
219
                    + "          \"-value\": \"3_9\",\n"
220
                    + "          \"-text\": \"три,четыре,пять,шесть,семь,восемь,девять\"\n"
221
                    + "        },\n"
222
                    + "        {\n"
223
                    + "          \"-value\": \"100_900\",\n"
224
                    + "          \"-text\": \"сто ,двести ,триста ,четыреста ,пятьсот ,шестьсот ,семьсот ,восемьсот ,девятьсот \"\n"
225
                    + "        },\n"
226
                    + "        {\n"
227
                    + "          \"-value\": \"20_90\",\n"
228
                    + "          \"-text\": \"двадцать ,тридцать ,сорок ,пятьдесят ,шестьдесят ,семьдесят ,восемьдесят ,девяносто \"\n"
229
                    + "        },\n"
230
                    + "        {\n"
231
                    + "          \"-value\": \"pdv\",\n"
232
                    + "          \"-text\": \"в т.ч. НДС \"\n"
233
                    + "        },\n"
234
                    + "        {\n"
235
                    + "          \"-value\": \"pdv_value\",\n"
236
                    + "          \"-text\": \"18\"\n"
237
                    + "        }\n"
238
                    + "      ]\n"
239
                    + "    },\n"
240
                    + "    \"ENG\": {\n"
241
                    + "      \"item\": [\n"
242
                    + "        {\n"
243
                    + "          \"-value\": \"minus\",\n"
244
                    + "          \"-text\": \"minus\"\n"
245
                    + "        },\n"
246
                    + "        {\n"
247
                    + "          \"-value\": \"0\",\n"
248
                    + "          \"-text\": \"zero\"\n"
249
                    + "        },\n"
250
                    + "        {\n"
251
                    + "          \"-value\": \"1000_10\",\n"
252
                    + "          \"-text\": \"thousand,million,billion,trillion\"\n"
253
                    + "        },\n"
254
                    + "        {\n"
255
                    + "          \"-value\": \"1000_1\",\n"
256
                    + "          \"-text\": \"thousand,million,billion,trillion\"\n"
257
                    + "        },\n"
258
                    + "        {\n"
259
                    + "          \"-value\": \"1000_234\",\n"
260
                    + "          \"-text\": \"thousand,million,billion,trillion\"\n"
261
                    + "        },\n"
262
                    + "        {\n"
263
                    + "          \"-value\": \"1000_5\",\n"
264
                    + "          \"-text\": \"thousand,million,billion,trillion\"\n"
265
                    + "        },\n"
266
                    + "        {\n"
267
                    + "          \"-value\": \"10_19\",\n"
268
                    + "          \"-text\": \"ten,eleven,twelve,thirteen,fourteen,fifteen,sixteen,seventeen,eighteen,nineteen\"\n"
269
                    + "        },\n"
270
                    + "        {\n"
271
                    + "          \"-value\": \"1\",\n"
272
                    + "          \"-text\": \"one,one,one,one\"\n"
273
                    + "        },\n"
274
                    + "        {\n"
275
                    + "          \"-value\": \"2\",\n"
276
                    + "          \"-text\": \"two,two,two,two\"\n"
277
                    + "        },\n"
278
                    + "        {\n"
279
                    + "          \"-value\": \"3_9\",\n"
280
                    + "          \"-text\": \"three,four,five,six,seven,eight,nine\"\n"
281
                    + "        },\n"
282
                    + "        {\n"
283
                    + "          \"-value\": \"100_900\",\n"
284
                    + "          \"-text\": \"one hundred ,two hundred ,three hundred ,four hundred ,five hundred ,six hundred ,seven hundred ,eight hundred ,nine hundred \"\n"
285
                    + "        },\n"
286
                    + "        {\n"
287
                    + "          \"-value\": \"20_90\",\n"
288
                    + "          \"-text\": \"twenty-,thirty-,forty-,fifty-,sixty-,seventy-,eighty-,ninety-\"\n"
289
                    + "        },\n"
290
                    + "        {\n"
291
                    + "          \"-value\": \"pdv\",\n"
292
                    + "          \"-text\": \"including VAT \"\n"
293
                    + "        },\n"
294
                    + "        {\n"
295
                    + "          \"-value\": \"pdv_value\",\n"
296
                    + "          \"-text\": \"10\"\n"
297
                    + "        }\n"
298
                    + "      ]\n"
299
                    + "    },\n"
300
                    + "    \"RUR\": [\n"
301
                    + "      {\n"
302
                    + "        \"-CurrID\": \"810\",\n"
303
                    + "        \"-CurrName\": \"Российские рубли\",\n"
304
                    + "        \"-language\": \"RUS\",\n"
305
                    + "        \"-RubOneUnit\": \"рубль\",\n"
306
                    + "        \"-RubTwoUnit\": \"рубля\",\n"
307
                    + "        \"-RubFiveUnit\": \"рублей\",\n"
308
                    + "        \"-RubSex\": \"M\",\n"
309
                    + "        \"-RubShortUnit\": \"руб.\",\n"
310
                    + "        \"-KopOneUnit\": \"копейка\",\n"
311
                    + "        \"-KopTwoUnit\": \"копейки\",\n"
312
                    + "        \"-KopFiveUnit\": \"копеек\",\n"
313
                    + "        \"-KopSex\": \"F\"\n"
314
                    + "      },\n"
315
                    + "      {\n"
316
                    + "        \"-CurrID\": \"810\",\n"
317
                    + "        \"-CurrName\": \"Российские рубли\",\n"
318
                    + "        \"-language\": \"UKR\",\n"
319
                    + "        \"-RubOneUnit\": \"рубль\",\n"
320
                    + "        \"-RubTwoUnit\": \"рублі\",\n"
321
                    + "        \"-RubFiveUnit\": \"рублів\",\n"
322
                    + "        \"-RubSex\": \"M\",\n"
323
                    + "        \"-RubShortUnit\": \"руб.\",\n"
324
                    + "        \"-KopOneUnit\": \"копійка\",\n"
325
                    + "        \"-KopTwoUnit\": \"копійки\",\n"
326
                    + "        \"-KopFiveUnit\": \"копійок\",\n"
327
                    + "        \"-KopSex\": \"F\"\n"
328
                    + "      },\n"
329
                    + "      {\n"
330
                    + "        \"-CurrID\": \"810\",\n"
331
                    + "        \"-CurrName\": \"Российские рубли\",\n"
332
                    + "        \"-language\": \"ENG\",\n"
333
                    + "        \"-RubOneUnit\": \"ruble\",\n"
334
                    + "        \"-RubTwoUnit\": \"rubles\",\n"
335
                    + "        \"-RubFiveUnit\": \"rubles\",\n"
336
                    + "        \"-RubSex\": \"M\",\n"
337
                    + "        \"-RubShortUnit\": \"RUR.\",\n"
338
                    + "        \"-KopOneUnit\": \"kopeck\",\n"
339
                    + "        \"-KopTwoUnit\": \"kopecks\",\n"
340
                    + "        \"-KopFiveUnit\": \"kopecks\",\n"
341
                    + "        \"-KopSex\": \"M\"\n"
342
                    + "      }\n"
343
                    + "    ],\n"
344
                    + "    \"UAH\": [\n"
345
                    + "      {\n"
346
                    + "        \"-CurrID\": \"980\",\n"
347
                    + "        \"-CurrName\": \"Украинскі гривні\",\n"
348
                    + "        \"-language\": \"RUS\",\n"
349
                    + "        \"-RubOneUnit\": \"гривня\",\n"
350
                    + "        \"-RubTwoUnit\": \"гривни\",\n"
351
                    + "        \"-RubFiveUnit\": \"гривень\",\n"
352
                    + "        \"-RubSex\": \"F\",\n"
353
                    + "        \"-RubShortUnit\": \"грн.\",\n"
354
                    + "        \"-KopOneUnit\": \"копейка\",\n"
355
                    + "        \"-KopTwoUnit\": \"копейки\",\n"
356
                    + "        \"-KopFiveUnit\": \"копеек\",\n"
357
                    + "        \"-KopSex\": \"F\"\n"
358
                    + "      },\n"
359
                    + "      {\n"
360
                    + "        \"-CurrID\": \"980\",\n"
361
                    + "        \"-CurrName\": \"Украинскі гривні\",\n"
362
                    + "        \"-language\": \"UKR\",\n"
363
                    + "        \"-RubOneUnit\": \"гривня\",\n"
364
                    + "        \"-RubTwoUnit\": \"гривні\",\n"
365
                    + "        \"-RubFiveUnit\": \"гривень\",\n"
366
                    + "        \"-RubSex\": \"F\",\n"
367
                    + "        \"-RubShortUnit\": \"грн.\",\n"
368
                    + "        \"-KopOneUnit\": \"копійка\",\n"
369
                    + "        \"-KopTwoUnit\": \"копійки\",\n"
370
                    + "        \"-KopFiveUnit\": \"копійок\",\n"
371
                    + "        \"-KopSex\": \"F\"\n"
372
                    + "      },\n"
373
                    + "      {\n"
374
                    + "        \"-CurrID\": \"980\",\n"
375
                    + "        \"-CurrName\": \"Украинскі гривні\",\n"
376
                    + "        \"-language\": \"ENG\",\n"
377
                    + "        \"-RubOneUnit\": \"hryvnia\",\n"
378
                    + "        \"-RubTwoUnit\": \"hryvnias\",\n"
379
                    + "        \"-RubFiveUnit\": \"hryvnias\",\n"
380
                    + "        \"-RubSex\": \"M\",\n"
381
                    + "        \"-RubShortUnit\": \"UAH.\",\n"
382
                    + "        \"-KopOneUnit\": \"kopeck\",\n"
383
                    + "        \"-KopTwoUnit\": \"kopecks\",\n"
384
                    + "        \"-KopFiveUnit\": \"kopecks\",\n"
385
                    + "        \"-KopSex\": \"M\"\n"
386
                    + "      }\n"
387
                    + "    ],\n"
388
                    + "    \"PLZ\": [\n"
389
                    + "      {\n"
390
                    + "        \"-CurrID\": \"980\",\n"
391
                    + "        \"-CurrName\": \"Украинскі гривні\",\n"
392
                    + "        \"-language\": \"RUS\",\n"
393
                    + "        \"-RubOneUnit\": \"гривня\",\n"
394
                    + "        \"-RubTwoUnit\": \"гривни\",\n"
395
                    + "        \"-RubFiveUnit\": \"гривень\",\n"
396
                    + "        \"-RubSex\": \"F\",\n"
397
                    + "        \"-RubShortUnit\": \"грн.\",\n"
398
                    + "        \"-KopOneUnit\": \"копейка\",\n"
399
                    + "        \"-KopTwoUnit\": \"копейки\",\n"
400
                    + "        \"-KopFiveUnit\": \"копеек\",\n"
401
                    + "        \"-KopSex\": \"F\"\n"
402
                    + "      },\n"
403
                    + "      {\n"
404
                    + "        \"-CurrID\": \"980\",\n"
405
                    + "        \"-CurrName\": \"Украинскі гривні\",\n"
406
                    + "        \"-language\": \"UKR\",\n"
407
                    + "        \"-RubOneUnit\": \"гривня\",\n"
408
                    + "        \"-RubTwoUnit\": \"гривні\",\n"
409
                    + "        \"-RubFiveUnit\": \"гривень\",\n"
410
                    + "        \"-RubSex\": \"F\",\n"
411
                    + "        \"-RubShortUnit\": \"грн.\",\n"
412
                    + "        \"-KopOneUnit\": \"копійка\",\n"
413
                    + "        \"-KopTwoUnit\": \"копійки\",\n"
414
                    + "        \"-KopFiveUnit\": \"копійок\",\n"
415
                    + "        \"-KopSex\": \"F\"\n"
416
                    + "      },\n"
417
                    + "      {\n"
418
                    + "        \"-CurrID\": \"980\",\n"
419
                    + "        \"-CurrName\": \"Украинскі гривні\",\n"
420
                    + "        \"-language\": \"POL\",\n"
421
                    + "        \"-RubOneUnit\": \"złotych\",\n"
422
                    + "        \"-RubTwoUnit\": \"złote\",\n"
423
                    + "        \"-RubFiveUnit\": \"złotych\",\n"
424
                    + "        \"-RubSex\": \"F\",\n"
425
                    + "        \"-RubShortUnit\": \"złot.\",\n"
426
                    + "        \"-KopOneUnit\": \"grosz\",\n"
427
                    + "        \"-KopTwoUnit\": \"grosze\",\n"
428
                    + "        \"-KopFiveUnit\": \"groszy\",\n"
429
                    + "        \"-KopSex\": \"F\"\n"
430
                    + "      },\n"
431
                    + "      {\n"
432
                    + "        \"-CurrID\": \"980\",\n"
433
                    + "        \"-CurrName\": \"Украинскі гривні\",\n"
434
                    + "        \"-language\": \"ENG\",\n"
435
                    + "        \"-RubOneUnit\": \"hryvnia\",\n"
436
                    + "        \"-RubTwoUnit\": \"hryvnias\",\n"
437
                    + "        \"-RubFiveUnit\": \"hryvnias\",\n"
438
                    + "        \"-RubSex\": \"M\",\n"
439
                    + "        \"-RubShortUnit\": \"UAH.\",\n"
440
                    + "        \"-KopOneUnit\": \"kopeck\",\n"
441
                    + "        \"-KopTwoUnit\": \"kopecks\",\n"
442
                    + "        \"-KopFiveUnit\": \"kopecks\",\n"
443
                    + "        \"-KopSex\": \"M\"\n"
444
                    + "      }\n"
445
                    + "    ],\n"
446
                    + "    \"USD\": [\n"
447
                    + "      {\n"
448
                    + "        \"-CurrID\": \"840\",\n"
449
                    + "        \"-CurrName\": \"Долари США\",\n"
450
                    + "        \"-language\": \"RUS\",\n"
451
                    + "        \"-RubOneUnit\": \"доллар\",\n"
452
                    + "        \"-RubTwoUnit\": \"доллара\",\n"
453
                    + "        \"-RubFiveUnit\": \"долларов\",\n"
454
                    + "        \"-RubSex\": \"M\",\n"
455
                    + "        \"-RubShortUnit\": \"дол.\",\n"
456
                    + "        \"-KopOneUnit\": \"цент\",\n"
457
                    + "        \"-KopTwoUnit\": \"цента\",\n"
458
                    + "        \"-KopFiveUnit\": \"центов\",\n"
459
                    + "        \"-KopSex\": \"M\"\n"
460
                    + "      },\n"
461
                    + "      {\n"
462
                    + "        \"-CurrID\": \"840\",\n"
463
                    + "        \"-CurrName\": \"Долари США\",\n"
464
                    + "        \"-language\": \"UKR\",\n"
465
                    + "        \"-RubOneUnit\": \"долар\",\n"
466
                    + "        \"-RubTwoUnit\": \"долара\",\n"
467
                    + "        \"-RubFiveUnit\": \"доларів\",\n"
468
                    + "        \"-RubSex\": \"M\",\n"
469
                    + "        \"-RubShortUnit\": \"дол.\",\n"
470
                    + "        \"-KopOneUnit\": \"цент\",\n"
471
                    + "        \"-KopTwoUnit\": \"цента\",\n"
472
                    + "        \"-KopFiveUnit\": \"центів\",\n"
473
                    + "        \"-KopSex\": \"M\"\n"
474
                    + "      },\n"
475
                    + "      {\n"
476
                    + "        \"-CurrID\": \"840\",\n"
477
                    + "        \"-CurrName\": \"Долари США\",\n"
478
                    + "        \"-language\": \"ENG\",\n"
479
                    + "        \"-RubOneUnit\": \"dollar\",\n"
480
                    + "        \"-RubTwoUnit\": \"dollars\",\n"
481
                    + "        \"-RubFiveUnit\": \"dollars\",\n"
482
                    + "        \"-RubSex\": \"M\",\n"
483
                    + "        \"-RubShortUnit\": \"USD.\",\n"
484
                    + "        \"-KopOneUnit\": \"cent\",\n"
485
                    + "        \"-KopTwoUnit\": \"cents\",\n"
486
                    + "        \"-KopFiveUnit\": \"cents\",\n"
487
                    + "        \"-KopSex\": \"M\"\n"
488
                    + "      }\n"
489
                    + "    ],\n"
490
                    + "    \"EUR\": [\n"
491
                    + "      {\n"
492
                    + "        \"-CurrID\": \"840\",\n"
493
                    + "        \"-CurrName\": \"Евро ЕС\",\n"
494
                    + "        \"-language\": \"RUS\",\n"
495
                    + "        \"-RubOneUnit\": \"евро\",\n"
496
                    + "        \"-RubTwoUnit\": \"евро\",\n"
497
                    + "        \"-RubFiveUnit\": \"евро\",\n"
498
                    + "        \"-RubSex\": \"M\",\n"
499
                    + "        \"-RubShortUnit\": \"евр.\",\n"
500
                    + "        \"-KopOneUnit\": \"цент\",\n"
501
                    + "        \"-KopTwoUnit\": \"цента\",\n"
502
                    + "        \"-KopFiveUnit\": \"центов\",\n"
503
                    + "        \"-KopSex\": \"M\"\n"
504
                    + "      },\n"
505
                    + "      {\n"
506
                    + "        \"-CurrID\": \"840\",\n"
507
                    + "        \"-CurrName\": \"Евро ЕС\",\n"
508
                    + "        \"-language\": \"UKR\",\n"
509
                    + "        \"-RubOneUnit\": \"євро\",\n"
510
                    + "        \"-RubTwoUnit\": \"євро\",\n"
511
                    + "        \"-RubFiveUnit\": \"євро\",\n"
512
                    + "        \"-RubSex\": \"M\",\n"
513
                    + "        \"-RubShortUnit\": \"дол.\",\n"
514
                    + "        \"-KopOneUnit\": \"цент\",\n"
515
                    + "        \"-KopTwoUnit\": \"цента\",\n"
516
                    + "        \"-KopFiveUnit\": \"центів\",\n"
517
                    + "        \"-KopSex\": \"M\"\n"
518
                    + "      },\n"
519
                    + "      {\n"
520
                    + "        \"-CurrID\": \"840\",\n"
521
                    + "        \"-CurrName\": \"Долари США\",\n"
522
                    + "        \"-language\": \"ENG\",\n"
523
                    + "        \"-RubOneUnit\": \"euro\",\n"
524
                    + "        \"-RubTwoUnit\": \"euros\",\n"
525
                    + "        \"-RubFiveUnit\": \"euros\",\n"
526
                    + "        \"-RubSex\": \"M\",\n"
527
                    + "        \"-RubShortUnit\": \"USD.\",\n"
528
                    + "        \"-KopOneUnit\": \"cent\",\n"
529
                    + "        \"-KopTwoUnit\": \"cents\",\n"
530
                    + "        \"-KopFiveUnit\": \"cents\",\n"
531
                    + "        \"-KopSex\": \"M\"\n"
532
                    + "      }\n"
533
                    + "    ],\n"
534
                    + "    \"PER10\": [\n"
535
                    + "      {\n"
536
                    + "        \"-CurrID\": \"556\",\n"
537
                    + "        \"-CurrName\": \"Вiдсотки з десятими частинами\",\n"
538
                    + "        \"-language\": \"RUS\",\n"
539
                    + "        \"-RubOneUnit\": \"целая,\",\n"
540
                    + "        \"-RubTwoUnit\": \"целых,\",\n"
541
                    + "        \"-RubFiveUnit\": \"целых,\",\n"
542
                    + "        \"-RubSex\": \"F\",\n"
543
                    + "        \"-KopOneUnit\": \"десятая процента\",\n"
544
                    + "        \"-KopTwoUnit\": \"десятых процента\",\n"
545
                    + "        \"-KopFiveUnit\": \"десятых процента\",\n"
546
                    + "        \"-KopSex\": \"F\"\n"
547
                    + "      },\n"
548
                    + "      {\n"
549
                    + "        \"-CurrID\": \"556\",\n"
550
                    + "        \"-CurrName\": \"Вiдсотки з десятими частинами\",\n"
551
                    + "        \"-language\": \"UKR\",\n"
552
                    + "        \"-RubOneUnit\": \"ціла,\",\n"
553
                    + "        \"-RubTwoUnit\": \"цілих,\",\n"
554
                    + "        \"-RubFiveUnit\": \"цілих,\",\n"
555
                    + "        \"-RubSex\": \"F\",\n"
556
                    + "        \"-KopOneUnit\": \"десята відсотка\",\n"
557
                    + "        \"-KopTwoUnit\": \"десятих відсотка\",\n"
558
                    + "        \"-KopFiveUnit\": \"десятих відсотка\",\n"
559
                    + "        \"-KopSex\": \"F\"\n"
560
                    + "      },\n"
561
                    + "      {\n"
562
                    + "        \"-CurrID\": \"560\",\n"
563
                    + "        \"-CurrName\": \"Вiдсотки з десятими частинами\",\n"
564
                    + "        \"-language\": \"ENG\",\n"
565
                    + "        \"-RubOneUnit\": \",\",\n"
566
                    + "        \"-RubTwoUnit\": \"integers,\",\n"
567
                    + "        \"-RubFiveUnit\": \"integers,\",\n"
568
                    + "        \"-RubSex\": \"F\",\n"
569
                    + "        \"-KopOneUnit\": \"tenth of one percent\",\n"
570
                    + "        \"-KopTwoUnit\": \"tenth of one percent\",\n"
571
                    + "        \"-KopFiveUnit\": \"tenth of one percent\",\n"
572
                    + "        \"-KopSex\": \"F\"\n"
573
                    + "      }\n"
574
                    + "    ],\n"
575
                    + "    \"PER100\": [\n"
576
                    + "      {\n"
577
                    + "        \"-CurrID\": \"557\",\n"
578
                    + "        \"-CurrName\": \"Вiдсотки з сотими частинами\",\n"
579
                    + "        \"-language\": \"RUS\",\n"
580
                    + "        \"-RubOneUnit\": \"целая,\",\n"
581
                    + "        \"-RubTwoUnit\": \"целых,\",\n"
582
                    + "        \"-RubFiveUnit\": \"целых,\",\n"
583
                    + "        \"-RubSex\": \"F\",\n"
584
                    + "        \"-KopOneUnit\": \"сотая процента\",\n"
585
                    + "        \"-KopTwoUnit\": \"сотых процента\",\n"
586
                    + "        \"-KopFiveUnit\": \"сотых процента\",\n"
587
                    + "        \"-KopSex\": \"F\"\n"
588
                    + "      },\n"
589
                    + "      {\n"
590
                    + "        \"-CurrID\": \"557\",\n"
591
                    + "        \"-CurrName\": \"Вiдсотки з сотими частинами\",\n"
592
                    + "        \"-language\": \"UKR\",\n"
593
                    + "        \"-RubOneUnit\": \"ціла,\",\n"
594
                    + "        \"-RubTwoUnit\": \"цілих,\",\n"
595
                    + "        \"-RubFiveUnit\": \"цілих,\",\n"
596
                    + "        \"-RubSex\": \"F\",\n"
597
                    + "        \"-KopOneUnit\": \"сота відсотка\",\n"
598
                    + "        \"-KopTwoUnit\": \"сотих відсотка\",\n"
599
                    + "        \"-KopFiveUnit\": \"сотих відсотка\",\n"
600
                    + "        \"-KopSex\": \"F\"\n"
601
                    + "      },\n"
602
                    + "      {\n"
603
                    + "        \"-CurrID\": \"561\",\n"
604
                    + "        \"-CurrName\": \"Вiдсотки з сотими частинами\",\n"
605
                    + "        \"-language\": \"ENG\",\n"
606
                    + "        \"-RubOneUnit\": \",\",\n"
607
                    + "        \"-RubTwoUnit\": \"integers,\",\n"
608
                    + "        \"-RubFiveUnit\": \"integers,\",\n"
609
                    + "        \"-RubSex\": \"F\",\n"
610
                    + "        \"-KopOneUnit\": \"hundred percent\",\n"
611
                    + "        \"-KopTwoUnit\": \"hundredth of percent\",\n"
612
                    + "        \"-KopFiveUnit\": \"hundredth of percent\",\n"
613
                    + "        \"-KopSex\": \"F\"\n"
614
                    + "      }\n"
615
                    + "    ],\n"
616
                    + "    \"PER1000\": [\n"
617
                    + "      {\n"
618
                    + "        \"-CurrID\": \"558\",\n"
619
                    + "        \"-CurrName\": \"Вiдсотки з тисячними частинами\",\n"
620
                    + "        \"-language\": \"RUS\",\n"
621
                    + "        \"-RubOneUnit\": \"целая,\",\n"
622
                    + "        \"-RubTwoUnit\": \"целых,\",\n"
623
                    + "        \"-RubFiveUnit\": \"целых,\",\n"
624
                    + "        \"-RubSex\": \"F\",\n"
625
                    + "        \"-KopOneUnit\": \"тысячная процента\",\n"
626
                    + "        \"-KopTwoUnit\": \"тысячных процента\",\n"
627
                    + "        \"-KopFiveUnit\": \"тысячных процента\",\n"
628
                    + "        \"-KopSex\": \"F\"\n"
629
                    + "      },\n"
630
                    + "      {\n"
631
                    + "        \"-CurrID\": \"558\",\n"
632
                    + "        \"-CurrName\": \"Вiдсотки з тисячними частинами\",\n"
633
                    + "        \"-language\": \"UKR\",\n"
634
                    + "        \"-RubOneUnit\": \"ціла,\",\n"
635
                    + "        \"-RubTwoUnit\": \"цілих,\",\n"
636
                    + "        \"-RubFiveUnit\": \"цілих,\",\n"
637
                    + "        \"-RubSex\": \"F\",\n"
638
                    + "        \"-KopOneUnit\": \"тисячна відсотка\",\n"
639
                    + "        \"-KopTwoUnit\": \"тисячних відсотка\",\n"
640
                    + "        \"-KopFiveUnit\": \"тисячних відсотка\",\n"
641
                    + "        \"-KopSex\": \"F\"\n"
642
                    + "      },\n"
643
                    + "      {\n"
644
                    + "        \"-CurrID\": \"562\",\n"
645
                    + "        \"-CurrName\": \"Вiдсотки з тисячними частинами\",\n"
646
                    + "        \"-language\": \"ENG\",\n"
647
                    + "        \"-RubOneUnit\": \",\",\n"
648
                    + "        \"-RubTwoUnit\": \"integers,\",\n"
649
                    + "        \"-RubFiveUnit\": \"integers,\",\n"
650
                    + "        \"-RubSex\": \"F\",\n"
651
                    + "        \"-KopOneUnit\": \"thousandth of percent\",\n"
652
                    + "        \"-KopTwoUnit\": \"thousandths of percent\",\n"
653
                    + "        \"-KopFiveUnit\": \"thousandths of percent\",\n"
654
                    + "        \"-KopSex\": \"F\"\n"
655
                    + "      }\n"
656
                    + "    ],\n"
657
                    + "    \"PER10000\": [\n"
658
                    + "      {\n"
659
                    + "        \"-CurrID\": \"559\",\n"
660
                    + "        \"-CurrName\": \"Вiдсотки з десяти тисячними частинами\",\n"
661
                    + "        \"-language\": \"RUS\",\n"
662
                    + "        \"-RubOneUnit\": \"целая,\",\n"
663
                    + "        \"-RubTwoUnit\": \"целых,\",\n"
664
                    + "        \"-RubFiveUnit\": \"целых,\",\n"
665
                    + "        \"-RubSex\": \"F\",\n"
666
                    + "        \"-KopOneUnit\": \"десятитысячная процента\",\n"
667
                    + "        \"-KopTwoUnit\": \"десятитысячные процента\",\n"
668
                    + "        \"-KopFiveUnit\": \"десятитысячных процента\",\n"
669
                    + "        \"-KopSex\": \"F\"\n"
670
                    + "      },\n"
671
                    + "      {\n"
672
                    + "        \"-CurrID\": \"559\",\n"
673
                    + "        \"-CurrName\": \"Вiдсотки з десяти тисячними частинами\",\n"
674
                    + "        \"-language\": \"UKR\",\n"
675
                    + "        \"-RubOneUnit\": \"ціла,\",\n"
676
                    + "        \"-RubTwoUnit\": \"цілих,\",\n"
677
                    + "        \"-RubFiveUnit\": \"цілих,\",\n"
678
                    + "        \"-RubSex\": \"F\",\n"
679
                    + "        \"-KopOneUnit\": \"десятитисячна відсотка\",\n"
680
                    + "        \"-KopTwoUnit\": \"десятитисячних відсотка\",\n"
681
                    + "        \"-KopFiveUnit\": \"десятитисячних відсотка\",\n"
682
                    + "        \"-KopSex\": \"M\"\n"
683
                    + "      },\n"
684
                    + "      {\n"
685
                    + "        \"-CurrID\": \"563\",\n"
686
                    + "        \"-CurrName\": \"Вiдсотки з десяти тисячними частинами\",\n"
687
                    + "        \"-language\": \"ENG\",\n"
688
                    + "        \"-RubOneUnit\": \",\",\n"
689
                    + "        \"-RubTwoUnit\": \"integers,\",\n"
690
                    + "        \"-RubFiveUnit\": \"integers,\",\n"
691
                    + "        \"-RubSex\": \"F\",\n"
692
                    + "        \"-KopOneUnit\": \"ten percent\",\n"
693
                    + "        \"-KopTwoUnit\": \"ten-percent\",\n"
694
                    + "        \"-KopFiveUnit\": \"ten-percent\",\n"
695
                    + "        \"-KopSex\": \"F\"\n"
696
                    + "      }\n"
697
                    + "    ]\n"
698
                    + "  }\n"
699
                    + "}";
700

701
    public static class FromJson {
×
702
        public static class ParseException extends RuntimeException {
703
            private final int offset;
704
            private final int line;
705
            private final int column;
706

707
            public ParseException(String message, int offset, int line, int column) {
708
                super(message + " at " + line + ":" + column);
1✔
709
                this.offset = offset;
1✔
710
                this.line = line;
1✔
711
                this.column = column;
1✔
712
            }
1✔
713

714
            public int getOffset() {
715
                return offset;
×
716
            }
717

718
            public int getLine() {
719
                return line;
×
720
            }
721

722
            public int getColumn() {
723
                return column;
×
724
            }
725
        }
726

727
        public static class JsonParser {
728
            private final String json;
729
            private int index;
730
            private int line;
731
            private int lineOffset;
732
            private int current;
733
            private StringBuilder captureBuffer;
734
            private int captureStart;
735

736
            public JsonParser(String string) {
1✔
737
                this.json = string;
1✔
738
                line = 1;
1✔
739
                captureStart = -1;
1✔
740
            }
1✔
741

742
            public Object parse() {
743
                read();
1✔
744
                skipWhiteSpace();
1✔
745
                final Object result = readValue();
1✔
746
                skipWhiteSpace();
1✔
747
                if (!isEndOfText()) {
1✔
748
                    throw error("Unexpected character");
×
749
                }
750
                return result;
1✔
751
            }
752

753
            private Object readValue() {
754
                switch (current) {
1✔
755
                    case 'n':
756
                        return readNull();
×
757
                    case 't':
758
                        return readTrue();
×
759
                    case 'f':
760
                        return readFalse();
×
761
                    case '"':
762
                        return readString();
1✔
763
                    case '[':
764
                        return readArray();
1✔
765
                    case '{':
766
                        return readObject();
1✔
767
                    case '-':
768
                    case '0':
769
                    case '1':
770
                    case '2':
771
                    case '3':
772
                    case '4':
773
                    case '5':
774
                    case '6':
775
                    case '7':
776
                    case '8':
777
                    case '9':
778
                        return readNumber();
×
779
                    default:
780
                        throw expected("value");
1✔
781
                }
782
            }
783

784
            private List<Object> readArray() {
785
                read();
1✔
786
                List<Object> array = new ArrayList<>();
1✔
787
                skipWhiteSpace();
1✔
788
                if (readChar(']')) {
1✔
789
                    return array;
×
790
                }
791
                do {
792
                    skipWhiteSpace();
1✔
793
                    array.add(readValue());
1✔
794
                    skipWhiteSpace();
1✔
795
                } while (readChar(','));
1✔
796
                if (!readChar(']')) {
1✔
797
                    throw expected("',' or ']'");
×
798
                }
799
                return array;
1✔
800
            }
801

802
            private Map<String, Object> readObject() {
803
                read();
1✔
804
                Map<String, Object> object = new LinkedHashMap<>();
1✔
805
                skipWhiteSpace();
1✔
806
                if (readChar('}')) {
1✔
807
                    return object;
×
808
                }
809
                do {
810
                    skipWhiteSpace();
1✔
811
                    String name = readName();
1✔
812
                    skipWhiteSpace();
1✔
813
                    if (!readChar(':')) {
1✔
814
                        throw expected("':'");
×
815
                    }
816
                    skipWhiteSpace();
1✔
817
                    object.put(name, readValue());
1✔
818
                    skipWhiteSpace();
1✔
819
                } while (readChar(','));
1✔
820
                if (!readChar('}')) {
1✔
821
                    throw expected("',' or '}'");
×
822
                }
823
                return object;
1✔
824
            }
825

826
            private String readName() {
827
                if (current != '"') {
1✔
828
                    throw expected("name");
×
829
                }
830
                return readString();
1✔
831
            }
832

833
            private String readNull() {
834
                read();
×
835
                readRequiredChar('u');
×
836
                readRequiredChar('l');
×
837
                readRequiredChar('l');
×
838
                return null;
×
839
            }
840

841
            private Boolean readTrue() {
842
                read();
×
843
                readRequiredChar('r');
×
844
                readRequiredChar('u');
×
845
                readRequiredChar('e');
×
846
                return Boolean.TRUE;
×
847
            }
848

849
            private Boolean readFalse() {
850
                read();
×
851
                readRequiredChar('a');
×
852
                readRequiredChar('l');
×
853
                readRequiredChar('s');
×
854
                readRequiredChar('e');
×
855
                return Boolean.FALSE;
×
856
            }
857

858
            private void readRequiredChar(char ch) {
859
                if (!readChar(ch)) {
×
860
                    throw expected("'" + ch + "'");
×
861
                }
862
            }
×
863

864
            private String readString() {
865
                read();
1✔
866
                startCapture();
1✔
867
                while (current != '"') {
1✔
868
                    if (current == '\\') {
1✔
869
                        pauseCapture();
×
870
                        readEscape();
×
871
                        startCapture();
×
872
                    } else if (current < 0x20) {
1✔
873
                        throw expected("valid string character");
×
874
                    } else {
875
                        read();
1✔
876
                    }
877
                }
878
                String string = endCapture();
1✔
879
                read();
1✔
880
                return string;
1✔
881
            }
882

883
            private void readEscape() {
884
                read();
×
885
                switch (current) {
×
886
                    case '"':
887
                    case '/':
888
                    case '\\':
889
                        captureBuffer.append((char) current);
×
890
                        break;
×
891
                    case 'b':
892
                        captureBuffer.append('\b');
×
893
                        break;
×
894
                    case 'f':
895
                        captureBuffer.append('\f');
×
896
                        break;
×
897
                    case 'n':
898
                        captureBuffer.append('\n');
×
899
                        break;
×
900
                    case 'r':
901
                        captureBuffer.append('\r');
×
902
                        break;
×
903
                    case 't':
904
                        captureBuffer.append('\t');
×
905
                        break;
×
906
                    case 'u':
907
                        char[] hexChars = new char[4];
×
908
                        boolean isHexCharsDigits = true;
×
909
                        for (int i = 0; i < 4; i++) {
×
910
                            read();
×
911
                            if (!isHexDigit()) {
×
912
                                isHexCharsDigits = false;
×
913
                            }
914
                            hexChars[i] = (char) current;
×
915
                        }
916
                        if (isHexCharsDigits) {
×
917
                            captureBuffer.append((char) Integer.parseInt(new String(hexChars), 16));
×
918
                        } else {
919
                            captureBuffer
×
920
                                    .append("\\u")
×
921
                                    .append(hexChars[0])
×
922
                                    .append(hexChars[1])
×
923
                                    .append(hexChars[2])
×
924
                                    .append(hexChars[3]);
×
925
                        }
926
                        break;
×
927
                    default:
928
                        throw expected("valid escape sequence");
×
929
                }
930
                read();
×
931
            }
×
932

933
            private Number readNumber() {
934
                startCapture();
×
935
                readChar('-');
×
936
                int firstDigit = current;
×
937
                if (!readDigit()) {
×
938
                    throw expected("digit");
×
939
                }
940
                if (firstDigit != '0') {
×
941
                    while (readDigit()) {}
×
942
                }
943
                readFraction();
×
944
                readExponent();
×
945
                final String number = endCapture();
×
946
                if (number.contains(".") || number.contains("e") || number.contains("E")) {
×
947
                    return Double.valueOf(number);
×
948
                } else {
949
                    return Long.valueOf(number);
×
950
                }
951
            }
952

953
            private boolean readFraction() {
954
                if (!readChar('.')) {
×
955
                    return false;
×
956
                }
957
                if (!readDigit()) {
×
958
                    throw expected("digit");
×
959
                }
960
                while (readDigit()) {}
×
961
                return true;
×
962
            }
963

964
            private boolean readExponent() {
965
                if (!readChar('e') && !readChar('E')) {
×
966
                    return false;
×
967
                }
968
                if (!readChar('+')) {
×
969
                    readChar('-');
×
970
                }
971
                if (!readDigit()) {
×
972
                    throw expected("digit");
×
973
                }
974
                while (readDigit()) {}
×
975
                return true;
×
976
            }
977

978
            private boolean readChar(char ch) {
979
                if (current != ch) {
1✔
980
                    return false;
1✔
981
                }
982
                read();
1✔
983
                return true;
1✔
984
            }
985

986
            private boolean readDigit() {
987
                if (!isDigit()) {
×
988
                    return false;
×
989
                }
990
                read();
×
991
                return true;
×
992
            }
993

994
            private void skipWhiteSpace() {
995
                while (isWhiteSpace()) {
1✔
996
                    read();
1✔
997
                }
998
            }
1✔
999

1000
            private void read() {
1001
                if (index == json.length()) {
1✔
1002
                    current = -1;
1✔
1003
                    return;
1✔
1004
                }
1005
                if (current == '\n') {
1✔
1006
                    line++;
1✔
1007
                    lineOffset = index;
1✔
1008
                }
1009
                current = json.charAt(index++);
1✔
1010
            }
1✔
1011

1012
            private void startCapture() {
1013
                if (captureBuffer == null) {
1✔
1014
                    captureBuffer = new StringBuilder();
1✔
1015
                }
1016
                captureStart = index - 1;
1✔
1017
            }
1✔
1018

1019
            private void pauseCapture() {
1020
                captureBuffer.append(json.substring(captureStart, index - 1));
×
1021
                captureStart = -1;
×
1022
            }
×
1023

1024
            private String endCapture() {
1025
                int end = current == -1 ? index : index - 1;
1✔
1026
                String captured;
1027
                if (captureBuffer.length() > 0) {
1✔
1028
                    captureBuffer.append(json.substring(captureStart, end));
×
1029
                    captured = captureBuffer.toString();
×
1030
                    captureBuffer.setLength(0);
×
1031
                } else {
1032
                    captured = json.substring(captureStart, end);
1✔
1033
                }
1034
                captureStart = -1;
1✔
1035
                return captured;
1✔
1036
            }
1037

1038
            private ParseException expected(String expected) {
1039
                if (isEndOfText()) {
1✔
1040
                    return error("Unexpected end of input");
×
1041
                }
1042
                return error("Expected " + expected);
1✔
1043
            }
1044

1045
            private ParseException error(String message) {
1046
                int absIndex = index;
1✔
1047
                int column = absIndex - lineOffset;
1✔
1048
                int offset = isEndOfText() ? absIndex : absIndex - 1;
1✔
1049
                return new ParseException(message, offset, line, column - 1);
1✔
1050
            }
1051

1052
            private boolean isWhiteSpace() {
1053
                return current == ' ' || current == '\t' || current == '\n' || current == '\r';
1✔
1054
            }
1055

1056
            private boolean isDigit() {
1057
                return current >= '0' && current <= '9';
×
1058
            }
1059

1060
            private boolean isHexDigit() {
1061
                return isDigit()
×
1062
                        || current >= 'a' && current <= 'f'
1063
                        || current >= 'A' && current <= 'F';
1064
            }
1065

1066
            private boolean isEndOfText() {
1067
                return current == -1;
1✔
1068
            }
1069
        }
1070

1071
        @SuppressWarnings("unchecked")
1072
        public static Map<String, Object> fromJson(String string) {
1073
            return (Map<String, Object>) new JsonParser(string).parse();
1✔
1074
        }
1075
    }
1076

1077
    private final java.util.Map<String, String[]> messages =
1✔
1078
            new java.util.LinkedHashMap<String, String[]>();
1079
    private final String rubOneUnit;
1080
    private final String rubTwoUnit;
1081
    private final String rubFiveUnit;
1082
    private final String rubSex;
1083
    private final String kopOneUnit;
1084
    private final String kopTwoUnit;
1085
    private final String kopFiveUnit;
1086
    private final String kopSex;
1087
    private final String rubShortUnit;
1088
    private final Currency currency;
1089
    private final Language language;
1090
    private final Pennies pennies;
1091

1092
    static {
1093
        initJsonMap(CURRENCY_LIST);
1✔
1094
    }
1✔
1095

1096
    public static void initJsonMap(final String json) {
1097
        jsonMap = FromJson.fromJson(json);
1✔
1098
    }
1✔
1099

1100
    /** Currency. */
1101
    public enum Currency {
1✔
1102
        /** . */
1103
        UAH,
1✔
1104
        /** . */
1105
        USD,
1✔
1106
        /** . */
1107
        EUR,
1✔
1108
        /** . */
1109
        PLZ,
1✔
1110
        /** . */
1111
        RUR,
1✔
1112
        /** . */
1113
        PER10,
1✔
1114
        /** . */
1115
        PER100,
1✔
1116
        /** . */
1117
        PER1000,
1✔
1118
        /** . */
1119
        PER10000,
1✔
1120
        /** . */
1121
        Custom
1✔
1122
    }
1123

1124
    /** Language. */
1125
    public enum Language {
1✔
1126
        /** . */
1127
        UKR,
1✔
1128
        /** . */
1129
        ENG,
1✔
1130
        /** . */
1131
        POL,
1✔
1132
        /** . */
1133
        RUS
1✔
1134
    }
1135

1136
    /** Pennies. */
1137
    public enum Pennies {
1✔
1138
        /** . */
1139
        NUMBER,
1✔
1140
        /** . */
1141
        TEXT
1✔
1142
    }
1143

1144
    /**
1145
     * Usage: MoneyToStr moneyToStr = new MoneyToStr( MoneyToStr.Currency.UAH,
1146
     * MoneyToStr.Language.UKR, MoneyToStr.Pennies.NUMBER);
1147
     *
1148
     * @param currency the currency (UAH, RUR, USD, EUR)
1149
     * @param language the language (UKR, RUS, ENG)
1150
     * @param pennies the pennies (NUMBER, TEXT)
1151
     */
1152
    @SuppressWarnings("unchecked")
1153
    public MoneyToStr(Currency currency, Language language, Pennies pennies) {
1✔
1154
        if (currency == null) {
1✔
1155
            throw new IllegalArgumentException("currency is null");
1✔
1156
        }
1157
        if (language == null) {
1✔
1158
            throw new IllegalArgumentException("language is null");
1✔
1159
        }
1160
        if (pennies == null) {
1✔
1161
            throw new IllegalArgumentException("pennies is null");
1✔
1162
        }
1163
        this.currency = currency;
1✔
1164
        this.language = language;
1✔
1165
        this.pennies = pennies;
1✔
1166
        String theISOstr = currency.name();
1✔
1167
        Map<String, Object> languageElement =
1✔
1168
                (Map<String, Object>)
1169
                        ((Map<String, Object>) jsonMap.get("CurrencyList")).get(language.name());
1✔
1170
        List<Map<String, Object>> items = (List<Map<String, Object>>) languageElement.get("item");
1✔
1171
        for (Map<String, Object> languageItem : items) {
1✔
1172
            messages.put(
1✔
1173
                    (String) languageItem.get("-value"),
1✔
1174
                    ((String) languageItem.get("-text")).split(","));
1✔
1175
        }
1✔
1176
        List<Map<String, Object>> theISOElements =
1✔
1177
                (List<Map<String, Object>>)
1178
                        ((Map<String, Object>) jsonMap.get("CurrencyList")).get(theISOstr);
1✔
1179
        Map<String, Object> theISOElement = null;
1✔
1180
        for (Map<String, Object> theISOElementLocal : theISOElements) {
1✔
1181
            if (theISOElementLocal.get("-language").equals(language.name())) {
1✔
1182
                theISOElement = theISOElementLocal;
1✔
1183
                break;
1✔
1184
            }
1185
        }
1✔
1186
        rubOneUnit = (String) theISOElement.get("-RubOneUnit");
1✔
1187
        rubTwoUnit = (String) theISOElement.get("-RubTwoUnit");
1✔
1188
        rubFiveUnit = (String) theISOElement.get("-RubFiveUnit");
1✔
1189
        kopOneUnit = (String) theISOElement.get("-KopOneUnit");
1✔
1190
        kopTwoUnit = (String) theISOElement.get("-KopTwoUnit");
1✔
1191
        kopFiveUnit = (String) theISOElement.get("-KopFiveUnit");
1✔
1192
        rubSex = (String) theISOElement.get("-RubSex");
1✔
1193
        kopSex = (String) theISOElement.get("-KopSex");
1✔
1194
        rubShortUnit =
1✔
1195
                theISOElement.containsKey("-RubShortUnit")
1✔
1196
                        ? (String) theISOElement.get("-RubShortUnit")
1✔
1197
                        : "";
1198
    }
1✔
1199

1200
    /**
1201
     * Inits class with currency. Usage: MoneyToStr moneyToStr = new MoneyToStr(
1202
     * MoneyToStr.Currency.UAH, MoneyToStr.Language.UKR, MoneyToStr.Pennies.NUMBER);
1203
     *
1204
     * @param currency the currency (UAH, RUR, USD, EUR)
1205
     * @param language the language (UKR, RUS, ENG)
1206
     * @param pennies the pennies (NUMBER, TEXT)
1207
     * @param names the custom names
1208
     */
1209
    @SuppressWarnings("unchecked")
1210
    public MoneyToStr(Currency currency, Language language, Pennies pennies, String[] names) {
1✔
1211
        if (currency == null) {
1✔
1212
            throw new IllegalArgumentException("currency is null");
1✔
1213
        }
1214
        if (language == null) {
1✔
1215
            throw new IllegalArgumentException("language is null");
1✔
1216
        }
1217
        if (pennies == null) {
1✔
1218
            throw new IllegalArgumentException("pennies is null");
1✔
1219
        }
1220
        if (names == null || names.length != 8) {
1✔
1221
            throw new IllegalArgumentException("names is null");
1✔
1222
        }
1223
        this.currency = currency;
1✔
1224
        this.language = language;
1✔
1225
        this.pennies = pennies;
1✔
1226
        Map<String, Object> languageElement =
1✔
1227
                (Map<String, Object>)
1228
                        ((Map<String, Object>) jsonMap.get("CurrencyList")).get(language.name());
1✔
1229
        List<Map<String, Object>> items = (List<Map<String, Object>>) languageElement.get("item");
1✔
1230
        for (Map<String, Object> languageItem : items) {
1✔
1231
            messages.put(
1✔
1232
                    (String) languageItem.get("-value"),
1✔
1233
                    ((String) languageItem.get("-text")).split(","));
1✔
1234
        }
1✔
1235
        rubOneUnit = names[0];
1✔
1236
        rubTwoUnit = names[1];
1✔
1237
        rubFiveUnit = names[2];
1✔
1238
        rubSex = names[3];
1✔
1239
        kopOneUnit = names[4];
1✔
1240
        kopTwoUnit = names[5];
1✔
1241
        kopFiveUnit = names[6];
1✔
1242
        kopSex = names[7];
1✔
1243
        rubShortUnit = names[0];
1✔
1244
    }
1✔
1245

1246
    /**
1247
     * Converts percent to string.
1248
     *
1249
     * @param amount the amount of percent
1250
     * @param lang the language (RUS, UKR)
1251
     * @return the string of percent
1252
     */
1253
    public static String percentToStr(Double amount, Language lang) {
1254
        return percentToStr(amount, lang, Pennies.TEXT);
1✔
1255
    }
1256

1257
    /**
1258
     * Converts percent to string.
1259
     *
1260
     * @param amount the amount of percent
1261
     * @param lang the language (RUS, UKR, ENG)
1262
     * @param pennies the pennies (NUMBER, TEXT)
1263
     * @return the string of percent
1264
     */
1265
    public static String percentToStr(Double amount, Language lang, Pennies pennies) {
1266
        if (amount == null) {
1✔
1267
            throw new IllegalArgumentException("amount is null");
1✔
1268
        }
1269
        if (lang == null) {
1✔
1270
            throw new IllegalArgumentException("language is null");
1✔
1271
        }
1272
        if (pennies == null) {
1✔
1273
            throw new IllegalArgumentException("pennies is null");
1✔
1274
        }
1275
        Long intPart = amount.longValue();
1✔
1276
        final long fractPart;
1277
        final String result;
1278
        int fractCount = BigDecimal.valueOf(amount).scale();
1✔
1279
        if (amount.floatValue() == amount.intValue()) {
1✔
1280
            result = new MoneyToStr(Currency.PER10, lang, pennies).convert(amount.longValue(), 0L);
1✔
1281
        } else if (fractCount == 1) {
1✔
1282
            fractPart = Math.round((amount - intPart) * NUM10);
1✔
1283
            result = new MoneyToStr(Currency.PER10, lang, pennies).convert(intPart, fractPart);
1✔
1284
        } else if (fractCount == 2) {
1✔
1285
            fractPart = Math.round((amount - intPart) * NUM100);
1✔
1286
            result = new MoneyToStr(Currency.PER100, lang, pennies).convert(intPart, fractPart);
1✔
1287
        } else if (fractCount == 3) {
1✔
1288
            fractPart = Math.round((amount - intPart) * NUM1000);
1✔
1289
            result = new MoneyToStr(Currency.PER1000, lang, pennies).convert(intPart, fractPart);
1✔
1290
        } else {
1291
            fractPart = Math.round((amount - intPart) * NUM10000);
1✔
1292
            result = new MoneyToStr(Currency.PER10000, lang, pennies).convert(intPart, fractPart);
1✔
1293
        }
1294
        return result;
1✔
1295
    }
1296

1297
    /**
1298
     * Converts double value to the text description.
1299
     *
1300
     * @param theMoney the amount of money in format major.minor
1301
     * @return the string description of money value
1302
     */
1303
    public String convert(Double theMoney) {
1304
        if (theMoney == null) {
1✔
1305
            throw new IllegalArgumentException("theMoney is null");
1✔
1306
        }
1307
        Long intPart = theMoney.longValue();
1✔
1308
        Long fractPart = Math.round((theMoney - intPart) * NUM100);
1✔
1309
        if (currency == Currency.PER1000) {
1✔
1310
            fractPart = Math.round((theMoney - intPart) * NUM1000);
1✔
1311
        }
1312
        return convert(intPart, fractPart);
1✔
1313
    }
1314

1315
    /**
1316
     * Converts amount to words. Usage: MoneyToStr moneyToStr = new
1317
     * MoneyToStr(MoneyToStr.Currency.UAH, MoneyToStr.Language.UKR, MoneyToStr.Pennies.NUMBER);
1318
     * String result = moneyToStr.convert(123D); Expected: result = сто двадцять три гривні 00
1319
     * копійок
1320
     *
1321
     * @param theMoney the amount of money major currency
1322
     * @param theKopeiki the amount of money minor currency
1323
     * @return the string description of money value
1324
     */
1325
    public String convert(Long theMoney, Long theKopeiki) {
1326
        if (theMoney == null) {
1✔
1327
            throw new IllegalArgumentException("theMoney is null");
1✔
1328
        }
1329
        if (theKopeiki == null) {
1✔
1330
            throw new IllegalArgumentException("theKopeiki is null");
1✔
1331
        }
1332
        StringBuilder money2str = new StringBuilder();
1✔
1333
        Long triadNum = 0L;
1✔
1334
        Long theTriad;
1335

1336
        Long intPart = Math.abs(theMoney);
1✔
1337
        if (intPart == 0) {
1✔
1338
            money2str.append(messages.get("0")[0] + " ");
1✔
1339
        }
1340
        do {
1341
            theTriad = intPart % NUM1000;
1✔
1342
            money2str.insert(0, triad2Word(theTriad, triadNum, rubSex));
1✔
1343
            if (triadNum == 0) {
1✔
1344
                if ((theTriad % NUM100) / NUM10 == NUM1) {
1✔
1345
                    money2str.append(rubFiveUnit);
1✔
1346
                } else {
1347
                    switch (Long.valueOf(theTriad % NUM10).byteValue()) {
1✔
1348
                        case NUM1:
1349
                            money2str.append(rubOneUnit);
1✔
1350
                            break;
1✔
1351
                        case NUM2:
1352
                        case NUM3:
1353
                        case NUM4:
1354
                            money2str.append(rubTwoUnit);
1✔
1355
                            break;
1✔
1356
                        default:
1357
                            money2str.append(rubFiveUnit);
1✔
1358
                            break;
1359
                    }
1360
                }
1361
            }
1362
            intPart /= NUM1000;
1✔
1363
            triadNum++;
1✔
1364
        } while (intPart > 0);
1✔
1365

1366
        if (theMoney < 0) {
1✔
1367
            money2str.insert(0, messages.get("minus")[0] + " ");
1✔
1368
        }
1369
        if (pennies == Pennies.TEXT) {
1✔
1370
            money2str
1✔
1371
                    .append(language == Language.ENG ? " and " : " ")
1✔
1372
                    .append(
1✔
1373
                            theKopeiki == 0
1✔
1374
                                    ? messages.get("0")[0] + " "
1✔
1375
                                    : triad2Word(Math.abs(theKopeiki), 0L, kopSex));
1✔
1376
        } else {
1377
            money2str.append(
1✔
1378
                    " "
1379
                            + (Math.abs(theKopeiki) < 10
1✔
1380
                                    ? "0" + Math.abs(theKopeiki)
1✔
1381
                                    : Math.abs(theKopeiki))
1✔
1382
                            + " ");
1383
        }
1384
        if (theKopeiki >= NUM11 && theKopeiki <= NUM14) {
1✔
1385
            money2str.append(kopFiveUnit);
1✔
1386
        } else {
1387
            switch ((byte) (theKopeiki % NUM10)) {
1✔
1388
                case NUM1:
1389
                    money2str.append(kopOneUnit);
1✔
1390
                    break;
1✔
1391
                case NUM2:
1392
                case NUM3:
1393
                case NUM4:
1394
                    money2str.append(kopTwoUnit);
1✔
1395
                    break;
1✔
1396
                default:
1397
                    money2str.append(kopFiveUnit);
1✔
1398
                    break;
1399
            }
1400
        }
1401
        return money2str.toString().trim();
1✔
1402
    }
1403

1404
    private String triad2Word(Long triad, Long triadNum, String sex) {
1405
        final StringBuilder triadWord = new StringBuilder(NUM100);
1✔
1406

1407
        if (triad == 0) {
1✔
1408
            return "";
1✔
1409
        }
1410

1411
        triadWord.append(
1✔
1412
                concat(new String[] {""}, messages.get("100_900"))[
1✔
1413
                        Long.valueOf(triad / NUM100).byteValue()]);
1✔
1414
        final Long range10 = (triad % NUM100) / NUM10;
1✔
1415
        triadWord.append(concat(new String[] {"", ""}, messages.get("20_90"))[range10.byteValue()]);
1✔
1416
        if (language == Language.ENG && triadWord.length() > 0 && triad % NUM10 == 0) {
1✔
1417
            triadWord.deleteCharAt(triadWord.length() - 1);
1✔
1418
            triadWord.append(" ");
1✔
1419
        }
1420

1421
        check2(triadNum, sex, triadWord, triad, range10);
1✔
1422
        switch (triadNum.byteValue()) {
1✔
1423
            case NUM0:
1424
                break;
1✔
1425
            case NUM1:
1426
            case NUM2:
1427
            case NUM3:
1428
            case NUM4:
1429
                if (range10 == NUM1) {
1✔
1430
                    triadWord.append(messages.get("1000_10")[triadNum.byteValue() - 1] + " ");
1✔
1431
                } else {
1432
                    final Long range = triad % NUM10;
1✔
1433
                    switch (range.byteValue()) {
1✔
1434
                        case NUM1:
1435
                            triadWord.append(
1✔
1436
                                    messages.get("1000_1")[triadNum.byteValue() - 1] + " ");
1✔
1437
                            break;
1✔
1438
                        case NUM2:
1439
                        case NUM3:
1440
                        case NUM4:
1441
                            triadWord.append(
1✔
1442
                                    messages.get("1000_234")[triadNum.byteValue() - 1] + " ");
1✔
1443
                            break;
1✔
1444
                        default:
1445
                            triadWord.append(
1✔
1446
                                    messages.get("1000_5")[triadNum.byteValue() - 1] + " ");
1✔
1447
                            break;
1448
                    }
1449
                }
1450
                break;
1✔
1451
            default:
1452
                triadWord.append("??? ");
1✔
1453
                break;
1454
        }
1455
        return triadWord.toString();
1✔
1456
    }
1457

1458
    /**
1459
     * @param triadNum the triad num
1460
     * @param sex the sex
1461
     * @param triadWord the triad word
1462
     * @param triad the triad
1463
     * @param range10 the range 10
1464
     */
1465
    private void check2(
1466
            Long triadNum, String sex, StringBuilder triadWord, Long triad, Long range10) {
1467
        final Long range = triad % NUM10;
1✔
1468
        if (range10 == 1) {
1✔
1469
            triadWord.append(messages.get("10_19")[range.byteValue()] + " ");
1✔
1470
        } else {
1471
            switch (range.byteValue()) {
1✔
1472
                case NUM1:
1473
                    if (triadNum == NUM1) {
1✔
1474
                        triadWord.append(messages.get("1")[INDEX_0] + " ");
1✔
1475
                    } else if (triadNum == NUM2 || triadNum == NUM3 || triadNum == NUM4) {
1✔
1476
                        triadWord.append(messages.get("1")[INDEX_1] + " ");
1✔
1477
                    } else if ("M".equals(sex)) {
1✔
1478
                        triadWord.append(messages.get("1")[INDEX_2] + " ");
1✔
1479
                    } else if ("F".equals(sex)) {
1✔
1480
                        triadWord.append(messages.get("1")[INDEX_3] + " ");
1✔
1481
                    }
1482
                    break;
1483
                case NUM2:
1484
                    if (triadNum == NUM1) {
1✔
1485
                        triadWord.append(messages.get("2")[INDEX_0] + " ");
1✔
1486
                    } else if (triadNum == NUM2 || triadNum == NUM3 || triadNum == NUM4) {
1✔
1487
                        triadWord.append(messages.get("2")[INDEX_1] + " ");
1✔
1488
                    } else if ("M".equals(sex)) {
1✔
1489
                        triadWord.append(messages.get("2")[INDEX_2] + " ");
1✔
1490
                    } else if ("F".equals(sex)) {
1✔
1491
                        triadWord.append(messages.get("2")[INDEX_3] + " ");
1✔
1492
                    }
1493
                    break;
1494
                case NUM3:
1495
                case NUM4:
1496
                case NUM5:
1497
                case NUM6:
1498
                case NUM7:
1499
                case NUM8:
1500
                case NUM9:
1501
                    triadWord.append(
1✔
1502
                            concat(new String[] {"", "", ""}, messages.get("3_9"))[
1✔
1503
                                            range.byteValue()]
1✔
1504
                                    + " ");
1505
                    break;
1✔
1506
                default:
1507
                    break;
1508
            }
1509
        }
1510
    }
1✔
1511

1512
    private <T> T[] concat(T[] first, T[] second) {
1513
        final T[] result = java.util.Arrays.copyOf(first, first.length + second.length);
1✔
1514
        System.arraycopy(second, 0, result, first.length, second.length);
1✔
1515
        return result;
1✔
1516
    }
1517

1518
    public static void main(String[] args) {
1519
        String amount = "123.25";
1✔
1520
        String language = "ENG";
1✔
1521
        String currency = "USD";
1✔
1522
        String pennies = "TEXT";
1✔
1523
        if (args.length == 0) {
1✔
1524
            System.out.println(
1✔
1525
                    "Usage: java -jar moneytostr.jar --amount=123.25 --language=rus|ukr|eng --currency=rur|uah|usd|eur --pennies=text|number");
1526
        } else {
1527
            for (String arg : args) {
1✔
1528
                if (arg.startsWith("--amount=")) {
1✔
1529
                    amount = arg.substring("--amount=".length()).trim().replace(",", ".");
1✔
1530
                } else if (arg.startsWith("--language=")) {
1✔
1531
                    language = arg.substring("--language=".length()).trim().toUpperCase();
1✔
1532
                } else if (arg.startsWith("--currency=")) {
1✔
1533
                    currency = arg.substring("--currency=".length()).trim().toUpperCase();
1✔
1534
                } else if (arg.startsWith("--pennies=")) {
1✔
1535
                    pennies = arg.substring("--pennies=".length()).trim().toUpperCase();
1✔
1536
                }
1537
            }
1538
            String result =
1✔
1539
                    new MoneyToStr(
1540
                                    Currency.valueOf(currency),
1✔
1541
                                    Language.valueOf(language),
1✔
1542
                                    Pennies.valueOf(pennies))
1✔
1543
                            .convert(Double.valueOf(amount));
1✔
1544
            System.out.println(result);
1✔
1545
        }
1546
    }
1✔
1547

1548
    public java.util.Map<String, String[]> getMessages() {
1549
        return messages;
1✔
1550
    }
1551

1552
    public String getRubShortUnit() {
1553
        return rubShortUnit;
1✔
1554
    }
1555

1556
    public Language getLanguage() {
1557
        return language;
1✔
1558
    }
1559
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc