/
Strings.java
327 lines (288 loc) · 11.6 KB
/
Strings.java
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
/*
* Copyright OmniFaces
*
* 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
*
* https://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.
*/
package org.omnifaces.el.functions;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.omnifaces.util.Faces.getLocale;
import static org.omnifaces.util.Utils.isEmpty;
import java.text.MessageFormat;
import java.text.Normalizer;
import java.text.Normalizer.Form;
import java.util.Base64;
import java.util.regex.Pattern;
import org.omnifaces.util.Faces;
import org.omnifaces.util.Utils;
/**
* <p>
* Collection of EL functions for string manipulation: <code>of:abbreviate()</code>, <code>of:capitalize()</code>, <code>of:concat()</code>,
* <code>of:prettyURL()</code>, <code>of:encodeURL()</code>, <code>of:encodeURI()</code>, <code>of:encodeBase64()</code>,
* <code>of:escapeJS()</code>, <code>of:stripTags()</code> and <code>of:formatX()</code>.
* <p>
* Instead of <code>of:formatX()</code>, you can also use <code><o:outputFormat></code>.
*
* @author Bauke Scholtz
*/
public final class Strings {
// Constants ------------------------------------------------------------------------------------------------------
private static final Pattern PATTERN_DIACRITICAL_MARKS = Pattern.compile("\\p{InCombiningDiacriticalMarks}+");
private static final Pattern PATTERN_NON_ALPHANUMERIC_CHARS = Pattern.compile("[^\\p{Alnum}]+");
private static final Pattern PATTERN_XML_TAGS = Pattern.compile("\\<[^\\>]*+\\>");
private static final Pattern PATTERN_MULTIPLE_SPACES = Pattern.compile("\\s\\s+");
// Constructors ---------------------------------------------------------------------------------------------------
private Strings() {
// Hide constructor.
}
// Utility --------------------------------------------------------------------------------------------------------
/**
* Abbreviate the given text on the given size limit with ellipsis.
* @param text The text to be abbreviated.
* @param size The size limit of the text.
* @return The abbreviated text, or the unmodified text if it is shorter than the size.
*/
public static String abbreviate(String text, int size) {
if (text == null) {
return null;
}
if (text.length() > size) {
return text.substring(0, size).trim() + "...";
}
return text;
}
/**
* Concatenate the string representation of the given objects. This is useful when you don't know beforehand if one
* of the both hands is a string or is <code>null</code>, otherwise the EL
* <code>#{bean.string1.concat(bean.string2)}</code> can just be used.
* @param left The left hand.
* @param right The right hand.
* @return The concatenated strings.
*/
public static String concat(Object left, Object right) {
if (left == null && right == null) {
return null;
}
if (left == null) {
return right.toString();
}
if (right == null) {
return left.toString();
}
return left.toString() + right.toString();
}
/**
* Capitalize the given string, i.e. uppercase the first character.
* @param string The string to be capitalized.
* @return The capitalized string.
* @since 1.1
*/
public static String capitalize(String string) {
if (string == null || string.isEmpty()) {
return string;
}
return new StringBuilder()
.append(Character.toTitleCase(string.charAt(0)))
.append(string.substring(1))
.toString();
}
/**
* Parenthesize the given object. This will only wrap the given object in parenthesis when it's not empty or zero.
* @param object The object to be parenthesized.
* @return The parenthesized object.
* @since 3.0
*/
public static String parenthesize(Object object) {
if (isEmpty(object) || "0".equals(object.toString())) {
return null;
}
return format("({0})", object);
}
/**
* Replace all matches of the given pattern on the given string with the given replacement.
* @param value The string to be replaced.
* @param pattern The regular expression pattern to be tested.
* @param replacement The string to be substituted for each match.
* @return True if the given string matches the given pattern.
* @see String#replaceAll(String, String)
* @since 1.5
*/
public static String replaceAll(String value, String pattern, String replacement) {
if (value == null) {
return null;
}
return value.replaceAll(pattern, replacement);
}
/**
* Returns true if the given string matches the given pattern.
* @param value The string to be matched.
* @param pattern The regular expression pattern to be tested.
* @return True if the given string matches the given pattern.
* @see String#matches(String)
* @since 1.5
*/
public static boolean matches(String value, String pattern) {
return value != null && value.matches(pattern);
}
/**
* URL-prettify the given string. It performs the following tasks:
* <ul>
* <li>Lowercase the string.
* <li>Remove combining diacritical marks.
* <li>Replace non-alphanumeric characters by hyphens.
* </ul>
* This is useful when populating links with dynamic paths obtained from user controlled variables, such as blog
* titles.
* @param string The string to be prettified.
* @return The prettified string.
*/
public static String prettyURL(String string) {
if (string == null) {
return null;
}
String normalized = Normalizer.normalize(string.toLowerCase(), Form.NFD);
String withoutDiacriticalMarks = PATTERN_DIACRITICAL_MARKS.matcher(normalized).replaceAll("");
return PATTERN_NON_ALPHANUMERIC_CHARS.matcher(withoutDiacriticalMarks).replaceAll("-");
}
/**
* URL-encode the given string using UTF-8. This is useful for cases where you can't use
* <code><f:param></code>.
* @param string The string to be URL-encoded.
* @return The URL-encoded string.
* @throws UnsupportedOperationException When this platform does not support UTF-8.
*/
public static String encodeURL(String string) {
return Utils.encodeURL(string);
}
/**
* URI-encode the given string using UTF-8. This is useful for cases where you need to embed path parameters in URLs.
* @param string The string to be URI-encoded.
* @return The URI-encoded string.
* @throws UnsupportedOperationException When this platform does not support UTF-8.
* @since 3.5
*/
public static String encodeURI(String string) {
return Utils.encodeURI(string);
}
/**
* Base64-encode the given string. This is useful for cases where you need to create data URLs.
* @param string The string to be Base64-encoded.
* @return The Base64-encoded string.
* @since 3.8
*/
public static String encodeBase64(String string) {
if (string == null) {
return null;
}
return Base64.getEncoder().encodeToString(string.getBytes(UTF_8));
}
/**
* Escapes the given string according the JavaScript code rules. This escapes among others the special characters,
* the whitespace, the quotes and the unicode characters. Useful whenever you want to use a Java string variable as
* a JavaScript string variable.
* @param string The string to be escaped according the JavaScript code rules.
* @return The escaped string according the JavaScript code rules.
*/
public static String escapeJS(String string) {
return Utils.escapeJS(string, true);
}
/**
* Remove XML tags from a string and return only plain text.
* @param string The string with XML tags.
* @return The string without XML tags.
* @since 3.7
*/
public static String stripTags(String string) {
if (string == null || string.isEmpty()) {
return string;
}
String withoutTags = PATTERN_XML_TAGS.matcher(string).replaceAll("");
return PATTERN_MULTIPLE_SPACES.matcher(withoutTags).replaceAll(" ").trim();
}
/**
* Format the given string with 1 parameter using {@link MessageFormat} API. The locale is obtained by
* {@link Faces#getLocale()}. Design notice: There are five formatX() methods, each taking 1 to 5 format parameters
* because EL functions do not support varargs methods nor overloaded function names.
* @param pattern The format pattern.
* @param param1 The first parameter.
* @return The formatted string.
* @see MessageFormat
*/
public static String format1(String pattern, Object param1) {
return format(pattern, param1);
}
/**
* Format the given string with 2 parameters using {@link MessageFormat} API. The locale is obtained by
* {@link Faces#getLocale()}. Design notice: There are five formatX() methods, each taking 1 to 5 format parameters
* because EL functions do not support varargs methods nor overloaded function names.
* @param pattern The format pattern.
* @param param1 The first parameter.
* @param param2 The second parameter.
* @return The formatted string.
* @see #format1(String, Object)
*/
public static String format2(String pattern, Object param1, Object param2) {
return format(pattern, param1, param2);
}
/**
* Format the given string with 3 parameters using {@link MessageFormat} API. The locale is obtained by
* {@link Faces#getLocale()}. Design notice: There are five formatX() methods, each taking 1 to 5 format parameters
* because EL functions do not support varargs methods nor overloaded function names.
* @param pattern The format pattern.
* @param param1 The first parameter.
* @param param2 The second parameter.
* @param param3 The third parameter.
* @return The formatted string.
* @see #format1(String, Object)
*/
public static String format3(String pattern, Object param1, Object param2, Object param3) {
return format(pattern, param1, param2, param3);
}
/**
* Format the given string with 4 parameters using {@link MessageFormat} API. The locale is obtained by
* {@link Faces#getLocale()}. Design notice: There are five formatX() methods, each taking 1 to 5 format parameters
* because EL functions do not support varargs methods nor overloaded function names.
* @param pattern The format pattern.
* @param param1 The first parameter.
* @param param2 The second parameter.
* @param param3 The third parameter.
* @param param4 The fourth parameter.
* @return The formatted string.
* @see #format1(String, Object)
*/
public static String format4(String pattern, Object param1, Object param2, Object param3, Object param4) {
return format(pattern, param1, param2, param3, param4);
}
/**
* Format the given string with 5 parameters using {@link MessageFormat} API. The locale is obtained by
* {@link Faces#getLocale()}. Design notice: There are five formatX() methods, each taking 1 to 5 format parameters
* because EL functions do not support varargs methods nor overloaded function names.
* @param pattern The format pattern.
* @param param1 The first parameter.
* @param param2 The second parameter.
* @param param3 The third parameter.
* @param param4 The fourth parameter.
* @param param5 The fifth parameter.
* @return The formatted string.
* @see #format1(String, Object)
*/
public static String format5
(String pattern, Object param1, Object param2, Object param3, Object param4, Object param5)
{
return format(pattern, param1, param2, param3, param4, param5);
}
/**
* The main string format method taking varargs.
*/
private static String format(String pattern, Object... params) {
StringBuffer result = new StringBuffer();
new MessageFormat(pattern, getLocale()).format(params, result, null);
return result.toString();
}
}