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