StringUtil xref

View Javadoc
1 /**
2  * BSD-style license; for more info see http://pmd.sourceforge.net/license.html 
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  * A number of String-specific utility methods for use by PMD or its IDE plugins.
12  *
13  * @author BrianRemedios
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  * Return whether the non-null text arg starts with any of the prefix
24  * values.
25  *
26  * @param text
27  * @param prefixes
28  * @return boolean
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  * Returns whether the non-null text arg matches any of the test values.
41  *
42  * @param text
43  * @param tests
44  * @return boolean
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  * Checks for the existence of any of the listed prefixes on the
57  * non-null text and removes them.
58  *
59  * @param text
60  * @param prefixes
61  * @return String
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  * Returns true if the value arg is either null, empty, or full of whitespace characters.
76  * More efficient that calling (string).trim().length() == 0
77  *
78  * @param value
79  * @return <code>true</code> if the value is empty, <code>false</code> otherwise.
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  * @param value String
99  * @return boolean
100  */
101 public static boolean isNotEmpty(String value) {
102 	return !isEmpty(value);
103 }
104 
105 /**
106  * Returns true if both strings are effectively null or whitespace,
107  * returns false otherwise if they have actual text that differs.
108  *
109  * @param a
110  * @param b
111  * @return boolean
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  * @param original String
124  * @param oldChar char
125  * @param newString String
126  * @return String
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  * @param original String
150  * @param oldString String
151  * @param newString String
152  * @return String
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  * Appends to a StringBuilder the String src where non-ASCII and
175  * XML special chars are escaped.
176  *
177  * @param buf The destination XML stream
178  * @param src The String to append to the stream
179  */
180 public static void appendXmlEscaped(StringBuilder buf, String src) {
181 appendXmlEscaped(buf, src, SUPPORTS_UTF8);
182 }
183 
184 /**
185  * Replace some whitespace characters so they are visually apparent.
186  * 
187  * @param o
188  * @return String
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  * @param string String
205  * @return String
206  */
207 public static String htmlEncode(String string) {
208 String encoded = replaceString(string, '&', "&amp;");
209 encoded = replaceString(encoded, '<', "&lt;");
210 return replaceString(encoded, '>', "&gt;");
211 }
212 
213 /**
214  *
215  * @param buf
216  * @param src
217  * @param supportUTF8 override the default setting, whether special characters should be replaced
218  * with entities (<code>false</code>) or should be included as is (<code>true</code>).
219  * @see #appendXmlEscaped(StringBuilder, String)
220  *
221  * TODO - unify the method above with the one below
222  *
223  * public to support unit testing - make this package private, once the unit test classes are in the same package.
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 > '~') {// 126
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("&amp;");
237 } else if (c == '"') {
238 buf.append("&quot;");
239 } else if (c == '<') {
240 buf.append("&lt;");
241 } else if (c == '>') {
242 buf.append("&gt;");
243 } else {
244 buf.append(c);
245 }
246 }
247 }
248 
249 	/**
250 	 * Parses the input source using the delimiter specified. This method is much
251 	 * faster than using the StringTokenizer or String.split(char) approach and
252 	 * serves as a replacement for String.split() for JDK1.3 that doesn't have it.
253  *
254  * FIXME - we're on JDK 1.4 now, can we replace this with String.split?
255 	 *
256 	 * @param source String
257 	 * @param delimiter char
258 	 * @return String[]
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 	 * Much more efficient than StringTokenizer.
299 	 *
300 	 * @param str String
301 	 * @param separator char
302 	 * @return String[]
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 	 * Copies the elements returned by the iterator onto the string buffer
330 	 * each delimited by the separator.
331 	 *
332 	 * @param sb StringBuffer
333 	 * @param iter Iterator
334 	 * @param separator String
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 	 * Copies the array items onto the string builder each delimited by the separator.
350 	 * Does nothing if the array is null or empty.
351 	 *
352 	 * @param sb StringBuilder
353 	 * @param items Object[]
354 	 * @param separator String
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 	 * Return the length of the shortest string in the array.
370 	 * If the collection is empty or any one of them is
371 	 * null then it returns 0.
372 	 *
373 	 * @param strings String[]
374 	 * @return int
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 	 * Determine the maximum number of common leading whitespace characters
394 	 * the strings share in the same sequence. Useful for determining how
395 	 * many leading characters can be removed to shift all the text in the
396 	 * strings to the left without misaligning them.
397 	 *
398 	 * @param strings String[]
399 	 * @return int
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 	 * Trims off the leading characters off the strings up to the trimDepth
429 	 * specified. Returns the same strings if trimDepth = 0
430 	 *
431 	 * @param strings
432 	 * @param trimDepth
433 	 * @return String[]
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  * Left pads a string.
450  * @param s The String to pad
451  * @param length The desired minimum length of the resulting padded String
452  * @return The resulting left padded String
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  * Are the two String values the same.
466  * The Strings can be optionally trimmed before checking.
467  * The Strings can be optionally compared ignoring case.
468  * The Strings can be have embedded whitespace standardized before comparing.
469  * Two null values are treated as equal.
470  *
471  * @param s1 The first String.
472  * @param s2 The second String.
473  * @param trim Indicates if the Strings should be trimmed before comparison.
474  * @param ignoreCase Indicates if the case of the Strings should ignored during comparison.
475  * @param standardizeWhitespace Indicates if the embedded whitespace should be standardized before comparison.
476  * @return <code>true</code> if the Strings are the same, <code>false</code> otherwise.
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 				// Replace all whitespace with a standard single space character.
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 	 * Formats all items onto a string with separators if more than one
500 	 * exists, return an empty string if the items are null or empty.
501 	 *
502 	 * @param items Object[]
503 	 * @param separator String
504 	 * @return String
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 }

AltStyle によって変換されたページ (->オリジナル) /