32
32
import java .util .regex .Pattern ;
33
33
34
34
/**
35
- * Format numbers according to the rules
36
- * {@see https://www.w3.org/TR/xpath-functions-31/#formatting-integers}
35
+ * Format numbers according to the rules for
36
+ * <a href=" https://www.w3.org/TR/xpath-functions-31/#formatting-integers">format-integer</a>
37
37
*/
38
38
public abstract class IntegerPicture {
39
39
40
- static IntegerPicture DEFAULT ;
41
-
42
- static {
43
- try {
44
- DEFAULT = new DigitsIntegerPicture ("1" , new FormatModifier ("" ));
45
- } catch (final XPathException e ) {
46
- e .printStackTrace ();
47
- }
48
- }
49
-
50
- final static BigInteger TEN = BigInteger .valueOf (10L );
40
+ static final BigInteger TEN = BigInteger .valueOf (10L );
51
41
52
42
//This contains \\v (vertical whitespace characters) so anything with vertical white space isn't a pattern
53
43
//It also disallows 0 instances of the pattern
54
44
//When decimal digit pattern doesn't match, we end up falling into a standard default.
55
- final static Pattern decimalDigitPattern = Pattern .compile ("^((\\ p{Nd}|#|[^\\ p{N}\\ p{L}\\ v])+)$" , Pattern .UNICODE_CHARACTER_CLASS );
56
- final static Pattern invalidDigitPattern = Pattern .compile ("(\\ p{Nd})" );
45
+ static final Pattern decimalDigitPattern = Pattern .compile ("^((\\ p{Nd}|#|[^\\ p{N}\\ p{L}\\ v])+)$" , Pattern .UNICODE_CHARACTER_CLASS );
46
+ static final Pattern invalidDigitPattern = Pattern .compile ("(\\ p{Nd})" );
57
47
58
48
/**
59
49
* The value of $picture consists of a primary format token,
@@ -81,19 +71,19 @@ public static IntegerPicture fromString(final String pictureFormat) throws XPath
81
71
}
82
72
83
73
// type 1 matcher (some digits)
84
- final Matcher decimalDigitMatcher = decimalDigitPattern .matcher (primaryFormatToken );
74
+ final Matcher decimalDigitMatcher = IntegerPicture . decimalDigitPattern .matcher (primaryFormatToken );
85
75
if (decimalDigitMatcher .matches ()) {
86
76
return new DigitsIntegerPicture (primaryFormatToken , formatModifier );
87
77
}
88
78
89
79
// incorrect type 1 matcher (and not anything else)
90
- final Matcher invalidDigitMatcher = invalidDigitPattern .matcher (primaryFormatToken );
80
+ final Matcher invalidDigitMatcher = IntegerPicture . invalidDigitPattern .matcher (primaryFormatToken );
91
81
if (invalidDigitMatcher .find ()) {
92
82
throw new XPathException (ErrorCodes .FODF1310 , "Invalid primary format token is not a valid decimal digital pattern: " + primaryFormatToken );
93
83
}
94
84
95
85
// specifically defined format token rules 2-8
96
- // {@see https://www.w3.org/TR/xpath-functions-31/#formatting-integers}
86
+ // <a href=" https://www.w3.org/TR/xpath-functions-31/#formatting-integers"/>
97
87
switch (primaryFormatToken ) {
98
88
case "A" :
99
89
return new SequenceIntegerPicture ('A' );
@@ -104,21 +94,21 @@ public static IntegerPicture fromString(final String pictureFormat) throws XPath
104
94
case "I" :
105
95
return new RomanIntegerPicture (true /*isUpper*/ );
106
96
case "W" :
107
- return new WordPicture (WordPicture .CaseAndCaps .Upper , formatModifier );
97
+ return new WordPicture (WordPicture .CaseAndCaps .UPPER , formatModifier );
108
98
case "w" :
109
- return new WordPicture (WordPicture .CaseAndCaps .Lower , formatModifier );
99
+ return new WordPicture (WordPicture .CaseAndCaps .LOWER , formatModifier );
110
100
case "Ww" :
111
- return new WordPicture (WordPicture .CaseAndCaps .Capitalized , formatModifier );
101
+ return new WordPicture (WordPicture .CaseAndCaps .CAPITALIZED , formatModifier );
112
102
default :
113
103
break ;
114
104
}
115
105
116
106
// Rule 9 - sequences
117
- // {@see https://www.w3.org/TR/xpath-functions-31/#formatting-integers}
118
- final List <Integer > codePoints = CodePoints (primaryFormatToken );
107
+ // <a href=" https://www.w3.org/TR/xpath-functions-31/#formatting-integers"/>
108
+ final List <Integer > codePoints = IntegerPicture . codePoints (primaryFormatToken );
119
109
final Optional <IntegerPicture > numberingPicture = NumberingPicture .fromIndexCodePoint (codePoints .get (0 ), formatModifier );
120
110
121
- return numberingPicture .orElse (defaultPictureWithModifier (formatModifier ));
111
+ return numberingPicture .orElse (IntegerPicture . defaultPictureWithModifier (formatModifier ));
122
112
}
123
113
124
114
static IntegerPicture defaultPictureWithModifier (final FormatModifier formatModifier ) throws XPathException {
@@ -131,10 +121,11 @@ static IntegerPicture defaultPictureWithModifier(final FormatModifier formatModi
131
121
* @param bigInteger the integer to format
132
122
* @param locale of the language to use in formatting
133
123
* @return a string containing the formatted integer
124
+ * @throws XPathException if the locale is ill-formed
134
125
*/
135
- abstract protected String formatInteger (BigInteger bigInteger , Locale locale ) throws XPathException ;
126
+ protected abstract String formatInteger (BigInteger bigInteger , Locale locale ) throws XPathException ;
136
127
137
- private Locale getLocaleFromLanguages (final List <String > languages ) throws XPathException {
128
+ private static Locale getLocaleFromLanguages (final List <String > languages ) throws XPathException {
138
129
139
130
IllformedLocaleException languageILE = null ;
140
131
for (final String language : languages ) {
@@ -146,12 +137,13 @@ private Locale getLocaleFromLanguages(final List<String> languages) throws XPath
146
137
languageILE = ile ;
147
138
}
148
139
}
140
+ assert languageILE != null ;
149
141
throw new XPathException (ErrorCodes .FODF1310 , languageILE .getMessage ());
150
142
}
151
143
152
144
public final String formatInteger (final BigInteger bigInteger , final List <String > languages ) throws XPathException {
153
145
154
- final Locale locale = getLocaleFromLanguages (languages );
146
+ final Locale locale = IntegerPicture . getLocaleFromLanguages (languages );
155
147
return formatInteger (bigInteger , locale );
156
148
}
157
149
@@ -161,17 +153,18 @@ public final String formatInteger(final BigInteger bigInteger, final List<String
161
153
* @param s the input string
162
154
* @return a list of the codepoints forming the string
163
155
*/
164
- protected static List <Integer > CodePoints (final String s ) {
156
+ protected static List <Integer > codePoints (final String s ) {
165
157
final List <Integer > codePointList = new ArrayList <>(s .length ());
166
- for (int i = 0 ; i < s .length (); ) {
158
+ int i = 0 ;
159
+ while (i < s .length ()) {
167
160
final int codePoint = Character .codePointAt (s , i );
168
161
i += Character .charCount (codePoint );
169
162
codePointList .add (codePoint );
170
163
}
171
164
return codePointList ;
172
165
}
173
166
174
- protected static String FromCodePoint (final int codePoint ) {
167
+ protected static String fromCodePoint (final int codePoint ) {
175
168
final StringBuilder sb = new StringBuilder ();
176
169
for (final char c : Character .toChars (codePoint )) {
177
170
sb .append (c );
@@ -187,6 +180,4 @@ protected static String ordinalSuffix(final int value, final Locale locale) {
187
180
for (; sb .length () > 0 && Character .isAlphabetic (sb .charAt (i )); i ++) ;
188
181
return sb .delete (i , sb .length ()).reverse ().toString ();
189
182
}
190
-
191
-
192
183
}
0 commit comments