Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Latest commit

 

History

History
History
728 lines (674 loc) · 25.3 KB

File metadata and controls

728 lines (674 loc) · 25.3 KB
Copy raw file
Download raw file
Open symbols panel
Edit and raw actions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
/**
* IString.java - international string
*
* Copyright 2013, JEDLSoft, All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Created on Jan 4, 2013 by edwin
*/
package com.ilib;
import java.io.File;
import java.io.InputStream;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.json.JSONException;
import org.json.JSONObject;
/**
* IString
*
* Represents an international string. This type of string allows for a
* formatting syntax very similar to the javascript ilib syntax, so that
* strings can be shared between code in java or javascript.
*
* @author edwin
*/
public class IString
{
public final static String EMPTY_ITEM = "";
protected final static String OPENED_BRACE = "\\{";
protected final static String CLOSED_BRACE = "}";
protected final static String NUMBER_SIGN = "#";
protected String text;
protected ArrayList<String> selectors = null;
protected ArrayList<String> strings = null;
protected String defaultChoice = null;
protected ArrayList<Pattern> patterns = null;
protected IlibLocale locale = null;
protected Map<String, String> plurals = null;
/**
* Construct a new IString instance with the given text.
*
* @param text the text to wrap
*/
public IString(String text)
{
this.text = text;
this.locale = new IlibLocale("en-US");
}
/**
* Construct a new IString instance with the given text and IlibLocale instance.
*
* @param text the text to wrap
* @param locale current locale
*/
public IString(String text, String locale)
{
this(text, new IlibLocale(locale));
}
/**
* Construct a new IString instance with the given text and IlibLocale instance.
*
* @param text the text to wrap
* @param locale current locale
*/
public IString(String text, IlibLocale locale)
{
this.text = text;
this.locale = locale;
}
/**
* Format a string with the given named values.
*
* The string can contain any text that a regular Java string can
* contain. Replacement parameters have the syntax:
*
* <pre>
* {name}
* </pre>
*
* Where "name" can be any string surrounded by curly brackets. The value of
* "name" is taken from the values argument.<p>
*
* Example:
*
* <pre>
* int numObjects = 12;
* IString str = new IString("There are {num} objects.");
* HashMap<String,String> values = new HashMap<String,String>();
* values.put("num", Integer.toString(numObjects));
* System.out.println(str.format(values));
* </pre>
*
* Would give the output:
*
* <pre>
* There are 12 objects.
* </pre>
*
* If a property is missing from the value map, the replacement
* parameter substring is left untouched in the string, and a different
* set of parameters may be applied a second time. This way, different
* parts of the code may format different parts of the message that they
* happen to know about.<p>
*
* Example:
*
* <pre>
* int numObjects = 12;
* IString str = new IString("There are {num} objects in the {container}.");
* HashMap<String,String> values = new HashMap<String,String>();
* values.put("num", Integer.toString(numObjects));
* System.out.println(str.format(values));
* </pre>
*
* Would give the output:<p>
*
* <pre>
* There are 12 objects in the {container}.
* </pre>
*
* The result can then be formatted again with a different value map that
* specifies a value for the "container" property.
*
* @param values a set of named values
* @return the string with as many replacement parameters
* replaced with named values as possible
*/
public String format(Map<String,String> values)
{
String formatted = text;
if ( values != null ) {
for ( String p: values.keySet() ) {
formatted = formatted.replaceAll(OPENED_BRACE + p + CLOSED_BRACE,
java.util.regex.Matcher.quoteReplacement(values.get(p)));
}
}
return formatted.toString();
}
/**
* This is the same as {@link IString#format(Map)} except the replacement
* values come from a JSON object instead of a map.
*
* @param values a set of named values in a JSON object
* @return the string with as many replacement parameters
* replaced with named values as possible
*/
public String format(JSONObject values)
{
String formatted = text;
if ( values != null ) {
Iterator<String> it = values.keys();
String p;
while ( it.hasNext() ) {
p = it.next();
try {
formatted = formatted.replaceAll(OPENED_BRACE + p + CLOSED_BRACE,
java.util.regex.Matcher.quoteReplacement(values.getString(p)));
} catch ( JSONException e ) {
// ignore
}
}
}
return formatted.toString();
}
protected void parseChoices()
throws ParseException
{
String[] choices = text.split("\\|");
int i;
String[] parts;
String str;
strings = new ArrayList<String>();
selectors = new ArrayList<String>();
defaultChoice = EMPTY_ITEM;
for ( i = 0; i < choices.length; i++ ) {
parts = choices[i].split(NUMBER_SIGN);
if ( parts.length > 2 ) {
str = choices[i].substring(choices[i].indexOf('#')+1);
} else if ( parts.length == 2 ) {
str = parts[1];
} else {
throw new ParseException("syntax error in choice format pattern: " + choices[i], i); // syntax error
}
selectors.add(parts[0]);
strings.add(str);
if ( parts[0].length() == 0 ) {
defaultChoice = str;
}
}
}
protected int getBooleanSelector(String selector)
{
if ( selector.equalsIgnoreCase("true") ||
selector.equalsIgnoreCase("yes") ||
selector.equalsIgnoreCase("on") ||
selector.equalsIgnoreCase("1") ) {
return 1;
} else if ( selector.equalsIgnoreCase("false") ||
selector.equalsIgnoreCase("no") ||
selector.equalsIgnoreCase("off") ||
selector.equalsIgnoreCase("0") ) {
return 0;
}
return -1;
}
protected IString getChoice(boolean reference)
throws ParseException
{
if ( text == null || text.length() == 0 ) {
return null;
}
int i;
IString result = null;
String selector;
if ( strings == null ) {
parseChoices();
}
for ( i = 0; i < selectors.size(); i++ ) {
selector = selectors.get(i);
int value = getBooleanSelector(selector);
if ( value == 1 ) {
if ( reference ) {
return new IString(strings.get(i));
}
} else if ( value == 0 ) {
if ( !reference ) {
return new IString(strings.get(i));
}
}
}
if ( result == null ) {
result = new IString(defaultChoice);
}
return result;
}
protected IString getChoice(String reference)
throws ParseException
{
if ( text == null || text.length() == 0 ) {
return null;
}
int i;
IString result = null;
String selector;
Pattern p;
Matcher m;
if ( strings == null ) {
parseChoices();
}
if ( patterns == null ) {
patterns = new ArrayList<Pattern>();
for (i = 0; i < selectors.size(); i++) {
selector = selectors.get(i);
patterns.add((selector != null && selector.length() > 0) ? Pattern.compile(selector, Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE) : null);
}
}
for ( i = 0; i < patterns.size(); i++ ) {
p = patterns.get(i);
if ( p != null ) {
m = p.matcher(reference);
if ( m.matches() ) {
return new IString(strings.get(i));
}
}
}
if ( result == null ) {
result = new IString(defaultChoice);
}
return result;
}
protected IString getChoice(double reference)
throws ParseException
{
if ( text == null || text.length() == 0 ) {
return null;
}
int i;
IString result = null;
double selector;
String sel;
if ( strings == null ) {
parseChoices();
}
if ( plurals == null ) {
ClassLoader cl = this.getClass().getClassLoader();
InputStream is = cl.getResourceAsStream("locale/" + (locale.getSpec().isEmpty() ? EMPTY_ITEM : locale.getLanguage() + File.separator) + PluralFormHelper.pluralsJSON);
//File pluralJSON = new File(PluralFormHelper.root,
// (locale.getSpec().isEmpty() ? EMPTY_ITEM : locale.getLanguage() + File.separator) + PluralFormHelper.pluralsJSON);
plurals = PluralFormHelper.getPluralForms(is);
if (plurals == null) plurals = new HashMap<>(0);
}
for (i = 0; i < selectors.size(); i++) {
sel = selectors.get(i);
if ( sel.length() > 2 && sel.substring(0,2).equals("<=") ) {
selector = Double.parseDouble(sel.substring(2));
if (reference <= selector) {
result = new IString(strings.get(i));
i = selectors.size();
}
} else if ( sel.length() > 2 && sel.substring(0,2).equals(">=") ) {
selector = Double.parseDouble(sel.substring(2));
if (reference >= selector) {
result = new IString(strings.get(i));
i = selectors.size();
}
} else if ( sel.length() > 1 && sel.charAt(0) == '<' ) {
selector = Double.parseDouble(sel.substring(1));
if (reference < selector) {
result = new IString(strings.get(i));
i = selectors.size();
}
} else if ( sel.length() > 1 && sel.charAt(0) == '>' ) {
selector = Double.parseDouble(sel.substring(1));
if (reference > selector) {
result = new IString(strings.get(i));
i = selectors.size();
}
} else if ( sel.length() > 0 ) {
if ( PluralFormHelper.getPluralKey((int)reference, plurals).equals(sel) ) {
result = new IString(strings.get(i), locale);
i = selectors.size();
} else {
int value, dash = sel.indexOf("-");
if ( dash != -1 ) {
// range
String start = sel.substring(0, dash);
String end = sel.substring(dash+1);
if (reference >= Long.parseLong(start, 10) && reference <= Long.parseLong(end, 10)) {
result = new IString(strings.get(i));
i = selectors.size();
}
} else if ( (value = getBooleanSelector(sel)) > -1 ) {
if ( value == reference ) {
result = new IString(strings.get(i));
i = selectors.size();
}
} else if (isNumeric(sel)) {
if ( reference == Long.parseLong(sel, 10) ) {
result = new IString(strings.get(i));
i = selectors.size();
}
}
}
}
}
if ( result == null ) {
result = new IString(defaultChoice);
}
return result;
}
public static boolean isNumeric(String str)
{
return str.matches("-?\\d+(\\.\\d+)?"); //match a number with optional '-' and decimal.
}
/**
* Format a string as one of a choice of strings dependent on the value of
* a particular reference argument.<p>
*
* The syntax of the choice string is as follows. The string contains a
* series of choices separated by a vertical bar character "|". Each choice
* has a selector, which is a value or range of values to match and an optional
* operator, followed by a hash character "#", followed by the string to use if
* the reference argument matches the criteria.<p>
*
* Example string:
*
* <pre>
* int num = 2;
* IString str = new IString("0#There are no objects.|1#There is one object.|2#There are {number} objects.");
* HashMap<String,String> values = new HashMap<String,String>();
* values.put("number", Integer.toString(num));
* System.out.println(str.formatChoice(num, values));
* </pre>
*
* Gives the output:
*
* <pre>
* "There are 2 objects."
* </pre>
*
* The strings to format may contain replacement variables that will be formatted
* using the {@link IString#format(Map)} method and the values argument as a source of values
* to use while formatting those variables.<p>
*
* If the selector for a particular choice is empty, that choice will be used
* as the default one for use when none of the other choice's criteria match.<p>
*
* Example string:
*
* <pre>
* int num = 22;
* IString str = new IString("0#There are no objects.|1#There is one object.|#There are {number} objects.");
* HashMap<String,String> values = new HashMap<String,String>();
* values.put("number", Integer.toString(num));
* System.out.println(str.formatChoice(num, values));
* </pre>
*
* Gives the output:
*
* <pre>
* "There are 22 objects."
* </pre>
*
* If multiple selectors can match a given reference argument, the first one
* encountered in the string will be used. If no selectors match the
* reference argument, then the default choice will be used. If there is no default
* choice defined, then this method will return an empty string.<p>
*
* <b>Special Syntax</b><p>
*
* For any choice format string, all of the selectors in the string should be of
* the same type. The available types are: numeric, boolean, or string/regexp. The type
* of the selectors is determined by the type of the reference argument.<p>
*
* If the reference argument is numeric, then some special operator syntax can be used
* in the selectors to match numeric ranges.<p>
*
* <ul>
* <li><i>&gt;x</i> - match any number that is greater than x
* <li><i>&gt;=x</i> - match any number that is greater than or equal to x
* <li><i>&lt;x</i> - match any number that is less than x
* <li><i>&lt;=x</i> - match any number that is less than or equal to x
* <li><i>start-end</i> - match any number in the range [start,end)
* </ul>
*
* If the type of the reference argument is boolean, the strings "true", "on", "yes", "1", or
* "false", "off", "no", or "0" (without the quotes) may appear as the selectors.<p>
*
* If the type of the reference argument is string, then the selectors may contain
* regular expressions, or just regular strings as if they were degenerate regexps.
*
* @param reference The reference value used to select the choice to use in the choice array
* @param values The map of parameter values that replace the replacement
* variables in the string
* @return the formatted string
*/
public String formatChoice(double reference, Map<String,String> values)
throws ParseException
{
IString result = getChoice(reference);
if ( result == null ) {
return EMPTY_ITEM;
}
return values != null ? result.format(values) : result.toString();
}
/**
* This is the same as {@link IString#formatChoice(double, Map)} except that the
* named replacement values come from a JSON object instead of a map.
*
* @see com.ilib.IString#formatChoice(double, Map)
* @param reference The reference value used to select the choice to use in the choice array
* @param values The JSON object containing parameter values that replace the
* replacement variables in the string
* @return the formatted string
*/
public String formatChoice(double reference, JSONObject values)
throws ParseException
{
IString result = getChoice(reference);
if ( result == null ) {
return EMPTY_ITEM;
}
return values != null ? result.format(values) : result.toString();
}
/**
* This is the same as {@link IString#formatChoice(double, Map)} but with null map.
*
* @see com.ilib.IString#formatChoice(double, Map)
* @param reference The reference value used to select the choice to use in the choice array
* @return the formatted string
*/
public String formatChoice(double reference) throws ParseException {
return formatChoice(reference, (Map<String, String>)null);
}
/**
* This is the same as {@link com.ilib.IString#formatChoice(double, Map)}
* except that the type of the reference argument is boolean. In this case, the
* strings "true", "on", "yes", "1", or "false", "off", "no", or "0" (without the
* quotes) may appear as the selectors. If a choice string with boolean selectors is
* formatted with a numeric argument index instead, then the value of "false" is
* taken to be 0, and the value of true is taken to be 1.
*
* @see com.ilib.IString#formatChoice(double, Map)
* @param reference The reference value used to select the choice to use in the choice array
* @param values The map of parameter values that replace the replacement
* variables in the string
* @return the formatted string
*/
public String formatChoice(boolean reference, Map<String,String> values)
throws ParseException
{
IString result = getChoice(reference);
if ( result == null ) {
return EMPTY_ITEM;
}
return values != null ? result.format(values) : result.toString();
}
/**
* This is the same as {@link IString#formatChoice(boolean, Map)} except that the
* named replacement values come from a JSON object instead of a map.
*
* @see com.ilib.IString#formatChoice(double, Map)
* @param reference The reference value used to select the choice to use in the choice array
* @param values The JSON object containing parameter values that replace the
* replacement variables in the string
* @return the formatted string
*/
public String formatChoice(boolean reference, JSONObject values)
throws ParseException
{
IString result = getChoice(reference);
if ( result == null ) {
return EMPTY_ITEM;
}
return values != null ? result.format(values) : result.toString();
}
/**
* This is the same as {@link com.ilib.IString#formatChoice(double, Map)}
* except that the type of the reference argument is a string which is matched
* against the regular expressions selectors in the choice string.
* A choice is selected if the regular expression
* matches the reference argument. The first choice that has its regexp match
* the reference argument is the one that is selected. Remember to escape
* any "#" or "|" characters in the regular expression so that they do not
* conflict with the syntax of the choice format string.
*
* @see com.ilib.IString#formatChoice(double, Map)
* @param reference The reference value used to select the choice to use in the choice array
* @param values The map of parameter values that replace the replacement
* variables in the string
* @return the formatted string
*/
public String formatChoice(String reference, Map<String,String> values)
throws ParseException
{
IString result = getChoice(reference);
if ( result == null ) {
return EMPTY_ITEM;
}
return values != null ? result.format(values) : result.toString();
}
/**
* This is the same as {@link IString#formatChoice(String, Map)} except that the
* named replacement values come from a JSON object instead of a map.
*
* @see com.ilib.IString#formatChoice(double, Map)
* @param reference The reference value used to select the choice to use in the choice array
* @param values The JSON object containing parameter values that replace the
* replacement variables in the string
* @return the formatted string
*/
public String formatChoice(String reference, JSONObject values)
throws ParseException
{
IString result = getChoice(reference);
if ( result == null ) {
return EMPTY_ITEM;
}
return values != null ? result.format(values) : result.toString();
}
/**
* Return the length of the given string in characters.
* @return the length of the given string in characters
*/
public int length()
{
return text.length();
}
/**
* Return locale associated with current IString instance.
* @return current locale
*/
public IlibLocale getLocale()
{
return locale;
}
/**
* Return locale of current IString instance.
* @param locale locale to be used for plurals translation
*/
public void setLocale(IlibLocale locale)
{
this.locale = locale;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
public String toString()
{
return text;
}
// convenience methods
/**
* Static convenience method to format choices without an IString instance.
*
* @param message string to format
* @param reference reference value
* @param parameters parameters to format into the string
* @return a formatted string
* @throws ParseException if the syntax of the choice format is wrong
*/
public static String formatChoice(String message, long reference, HashMap<String,String> parameters)
throws ParseException
{
return (new IString(message)).formatChoice((double)reference, parameters);
}
/**
* Static convenience method to format choices without an IString instance.
*
* @param message string to format
* @param reference reference value
* @param parameters parameters to format into the string
* @return a formatted string
* @throws ParseException if the syntax of the choice format is wrong
*/
public static String formatChoice(String message, double reference, HashMap<String,String> parameters)
throws ParseException
{
return (new IString(message)).formatChoice(reference, parameters);
}
/**
* Static convenience method to format choices without an IString instance.
*
* @param message string to format
* @param reference reference value
* @return a formatted string
* @throws ParseException if the syntax of the choice format is wrong
*/
public static String formatChoice(String message, long reference)
throws ParseException
{
return IString.formatChoice(message, reference, null);
}
/**
* Static convenience method to format without an IString instance.
*
* @param message string to format
* @param parameters parameters to format into the string
* @return a formatted string
*/
public static String format(String message, HashMap<String,String> parameters)
{
return (new IString(message)).format(parameters);
}
/**
* Static convenience method to format choices without an IString instance.
*
* @param message string to format
* @param reference reference value
* @return a formatted string
* @throws ParseException if the syntax of the choice format is wrong
*/
public static String formatChoice(String message, double reference)
throws ParseException
{
return IString.formatChoice(message, reference, null);
}
}
Morty Proxy This is a proxified and sanitized view of the page, visit original site.