1
2
3
4 package net.sourceforge.pmd.util;
5
6 import java.util.ArrayList;
7 import java.util.Iterator;
8 import java.util.List;
9
10
11
12
13
14
15
16 public final class StringUtil {
17
18 public static final String[] EMPTY_STRINGS = new String[0];
19 private static final boolean SUPPORTS_UTF8 = System.getProperty("net.sourceforge.pmd.supportUTF8", "no").equals(
20 "yes");
21
22 private StringUtil() {
23 }
24
25
26
27
28
29
30
31
32
33 public static boolean startsWithAny(String text, String... prefixes) {
34
35 for (String prefix : prefixes) {
36 if (text.startsWith(prefix)) {
37 return true;
38 }
39 }
40
41 return false;
42 }
43
44
45
46
47
48
49
50
51 public static boolean isAnyOf(String text, String... tests) {
52
53 for (String test : tests) {
54 if (text.equals(test)) {
55 return true;
56 }
57 }
58
59 return false;
60 }
61
62
63
64
65
66
67
68
69
70 public static String withoutPrefixes(String text, String... prefixes) {
71
72 for (String prefix : prefixes) {
73 if (text.startsWith(prefix)) {
74 return text.substring(prefix.length());
75 }
76 }
77
78 return text;
79 }
80
81
82
83
84
85
86
87
88
89
90 public static boolean isEmpty(String value) {
91
92 if (value == null || "".equals(value)) {
93 return true;
94 }
95
96 for (int i = 0; i < value.length(); i++) {
97 if (!Character.isWhitespace(value.charAt(i))) {
98 return false;
99 }
100 }
101
102 return true;
103 }
104
105
106
107
108
109
110 public static boolean isNotEmpty(String value) {
111 return !isEmpty(value);
112 }
113
114
115
116
117
118
119
120
121
122 public static boolean areSemanticEquals(String a, String b) {
123
124 if (a == null) {
125 return isEmpty(b);
126 }
127 if (b == null) {
128 return isEmpty(a);
129 }
130
131 return a.equals(b);
132 }
133
134
135
136
137
138
139
140
141 public static String replaceString(final String original, char oldChar, final String newString) {
142 int index = original.indexOf(oldChar);
143 if (index < 0) {
144 return original;
145 } else {
146 final String replace = newString == null ? "" : newString;
147 final StringBuilder buf = new StringBuilder(Math.max(16, original.length() + replace.length()));
148 int last = 0;
149 while (index != -1) {
150 buf.append(original.substring(last, index));
151 buf.append(replace);
152 last = index + 1;
153 index = original.indexOf(oldChar, last);
154 }
155 buf.append(original.substring(last));
156 return buf.toString();
157 }
158 }
159
160
161
162
163
164
165
166
167 public static String replaceString(final String original, final String oldString, final String newString) {
168 int index = original.indexOf(oldString);
169 if (index < 0) {
170 return original;
171 } else {
172 final String replace = newString == null ? "" : newString;
173 final StringBuilder buf = new StringBuilder(Math.max(16, original.length() + replace.length()));
174 int last = 0;
175 while (index != -1) {
176 buf.append(original.substring(last, index));
177 buf.append(replace);
178 last = index + oldString.length();
179 index = original.indexOf(oldString, last);
180 }
181 buf.append(original.substring(last));
182 return buf.toString();
183 }
184 }
185
186
187
188
189
190
191
192
193 public static void appendXmlEscaped(StringBuilder buf, String src) {
194 appendXmlEscaped(buf, src, SUPPORTS_UTF8);
195 }
196
197
198
199
200
201
202
203 public static String escapeWhitespace(Object o) {
204
205 if (o == null) {
206 return null;
207 }
208 String s = String.valueOf(o);
209 s = s.replace("\n", "\\n");
210 s = s.replace("\r", "\\r");
211 s = s.replace("\t", "\\t");
212 return s;
213 }
214
215
216
217
218
219
220 public static String htmlEncode(String string) {
221 String encoded = replaceString(string, '&', "&");
222 encoded = replaceString(encoded, '<', "<");
223 return replaceString(encoded, '>', ">");
224 }
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241 public static void appendXmlEscaped(StringBuilder buf, String src, boolean supportUTF8) {
242 char c;
243 for (int i = 0; i < src.length(); i++) {
244 c = src.charAt(i);
245 if (c > '~') {
246 if (!supportUTF8) {
247 buf.append("&#x").append(Integer.toHexString(c)).append(';');
248 } else {
249 buf.append(c);
250 }
251 } else if (c == '&') {
252 buf.append("&");
253 } else if (c == '"') {
254 buf.append(""");
255 } else if (c == '<') {
256 buf.append("<");
257 } else if (c == '>') {
258 buf.append(">");
259 } else {
260 buf.append(c);
261 }
262 }
263 }
264
265
266
267
268
269
270
271
272
273
274
275
276
277 public static String[] substringsOf(String source, char delimiter) {
278
279 if (source == null || source.length() == 0) {
280 return EMPTY_STRINGS;
281 }
282
283 int delimiterCount = 0;
284 int length = source.length();
285 char[] chars = source.toCharArray();
286
287 for (int i = 0; i < length; i++) {
288 if (chars[i] == delimiter) {
289 delimiterCount++;
290 }
291 }
292
293 if (delimiterCount == 0) {
294 return new String[] { source };
295 }
296
297 String[] results = new String[delimiterCount + 1];
298
299 int i = 0;
300 int offset = 0;
301
302 while (offset <= length) {
303 int pos = source.indexOf(delimiter, offset);
304 if (pos < 0) {
305 pos = length;
306 }
307 results[i++] = pos == offset ? "" : source.substring(offset, pos);
308 offset = pos + 1;
309 }
310
311 return results;
312 }
313
314
315
316
317
318
319
320
321 public static String[] substringsOf(String str, String separator) {
322
323 if (str == null || str.length() == 0) {
324 return EMPTY_STRINGS;
325 }
326
327 int index = str.indexOf(separator);
328 if (index == -1) {
329 return new String[] { str };
330 }
331
332 List<String> list = new ArrayList<String>();
333 int currPos = 0;
334 int len = separator.length();
335 while (index != -1) {
336 list.add(str.substring(currPos, index));
337 currPos = index + len;
338 index = str.indexOf(separator, currPos);
339 }
340 list.add(str.substring(currPos));
341 return list.toArray(new String[list.size()]);
342 }
343
344
345
346
347
348
349
350
351
352 public static void asStringOn(StringBuffer sb, Iterator<?> iter, String separator) {
353
354 if (!iter.hasNext()) {
355 return;
356 }
357
358 sb.append(iter.next());
359
360 while (iter.hasNext()) {
361 sb.append(separator);
362 sb.append(iter.next());
363 }
364 }
365
366
367
368
369
370
371
372
373
374 public static void asStringOn(StringBuilder sb, Object[] items, String separator) {
375
376 if (items == null || items.length == 0) {
377 return;
378 }
379
380 sb.append(items[0]);
381
382 for (int i = 1; i < items.length; i++) {
383 sb.append(separator);
384 sb.append(items[i]);
385 }
386 }
387
388
389
390
391
392
393
394
395 public static int lengthOfShortestIn(String[] strings) {
396
397 if (CollectionUtil.isEmpty(strings)) {
398 return 0;
399 }
400
401 int minLength = Integer.MAX_VALUE;
402
403 for (int i = 0; i < strings.length; i++) {
404 if (strings[i] == null) {
405 return 0;
406 }
407 minLength = Math.min(minLength, strings[i].length());
408 }
409
410 return minLength;
411 }
412
413
414
415
416
417
418
419
420
421
422 public static int maxCommonLeadingWhitespaceForAll(String[] strings) {
423
424 int shortest = lengthOfShortestIn(strings);
425 if (shortest == 0) {
426 return 0;
427 }
428
429 char[] matches = new char[shortest];
430
431 String str;
432 for (int m = 0; m < matches.length; m++) {
433 matches[m] = strings[0].charAt(m);
434 if (!Character.isWhitespace(matches[m])) {
435 return m;
436 }
437 for (int i = 0; i < strings.length; i++) {
438 str = strings[i];
439 if (str.charAt(m) != matches[m]) {
440 return m;
441 }
442 }
443 }
444
445 return shortest;
446 }
447
448
449
450
451
452
453
454
455
456 public static String[] trimStartOn(String[] strings, int trimDepth) {
457
458 if (trimDepth == 0) {
459 return strings;
460 }
461
462 String[] results = new String[strings.length];
463 for (int i = 0; i < strings.length; i++) {
464 results[i] = strings[i].substring(trimDepth);
465 }
466 return results;
467 }
468
469
470
471
472
473
474
475
476 public static String lpad(String s, int length) {
477 String res = s;
478 if (length - s.length() > 0) {
479 char[] arr = new char[length - s.length()];
480 java.util.Arrays.fill(arr, ' ');
481 res = new StringBuilder(length).append(arr).append(s).toString();
482 }
483 return res;
484 }
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502 @SuppressWarnings("PMD.CompareObjectsWithEquals")
503 public static boolean isSame(String s1, String s2, boolean trim, boolean ignoreCase, boolean standardizeWhitespace) {
504 if (s1 == s2) {
505 return true;
506 } else if (s1 == null || s2 == null) {
507 return false;
508 } else {
509 if (trim) {
510 s1 = s1.trim();
511 s2 = s2.trim();
512 }
513 if (standardizeWhitespace) {
514
515
516 s1 = s1.replaceAll("\\s+", " ");
517 s2 = s2.replaceAll("\\s+", " ");
518 }
519 return ignoreCase ? s1.equalsIgnoreCase(s2) : s1.equals(s2);
520 }
521 }
522
523
524
525
526
527
528
529
530
531 public static String asString(Object[] items, String separator) {
532
533 if (items == null || items.length == 0) {
534 return "";
535 }
536 if (items.length == 1) {
537 return items[0].toString();
538 }
539
540 StringBuilder sb = new StringBuilder(items[0].toString());
541 for (int i = 1; i < items.length; i++) {
542 sb.append(separator).append(items[i]);
543 }
544
545 return sb.toString();
546 }
547 }