1 package org.apache.maven.shared.utils;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 import java.util.Arrays;
24 import java.util.Iterator;
25 import java.util.Locale;
26 import java.util.Map;
27 import java.util.StringTokenizer;
28
29 import javax.annotation.Nonnull;
30 import javax.annotation.Nullable;
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 public class StringUtils
55 {
56
57
58
59
60
61
62
63
64 public StringUtils()
65 {
66 }
67
68
69
70
71
72
73
74
75
76
77
78
79
80 @Nonnull public static String clean( String str )
81 {
82 return ( str == null ? "" : str.trim() );
83 }
84
85
86
87
88
89
90
91
92
93
94 public static String trim( String str )
95 {
96 return ( str == null ? null : str.trim() );
97 }
98
99
100
101
102
103
104
105
106
107
108 @Nonnull public static String deleteWhitespace( @Nonnull String str )
109 {
110 StringBuilder buffer = new StringBuilder();
111 int sz = str.length();
112 for ( int i = 0; i < sz; i++ )
113 {
114 if ( !Character.isWhitespace( str.charAt( i ) ) )
115 {
116 buffer.append( str.charAt( i ) );
117 }
118 }
119 return buffer.toString();
120 }
121
122
123
124
125
126
127
128
129 public static boolean isNotEmpty( @Nullable String str )
130 {
131 return ( ( str != null ) && ( str.length() > 0 ) );
132 }
133
134
135
136
137
138
139
140
141
142
143
144
145 public static boolean isEmpty( @Nullable String str )
146 {
147 return ( ( str == null ) || ( str.trim().length() == 0 ) );
148 }
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167 public static boolean isBlank( @Nullable String str )
168 {
169 int strLen;
170
171 if ( str == null || ( strLen = str.length() ) == 0 )
172
173 {
174 return true;
175 }
176 for ( int i = 0; i < strLen; i++ )
177 {
178 if ( !Character.isWhitespace( str.charAt( i ) ) )
179 {
180 return false;
181 }
182 }
183 return true;
184 }
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203 public static boolean isNotBlank( @Nullable String str )
204 {
205 return !isBlank( str );
206 }
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224 @Deprecated
225 public static boolean equals( @Nullable String str1, @Nullable String str2 )
226 {
227 return ( str1 == null ? str2 == null : str1.equals( str2 ) );
228 }
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243 public static boolean equalsIgnoreCase( String str1, String str2 )
244 {
245 return ( str1 == null ? str2 == null : str1.equalsIgnoreCase( str2 ) );
246 }
247
248
249
250
251
252
253
254
255
256
257
258 public static int indexOfAny( String str, String... searchStrs )
259 {
260 if ( ( str == null ) || ( searchStrs == null ) )
261 {
262 return -1;
263 }
264
265 int ret = Integer.MAX_VALUE;
266
267 int tmp;
268 for ( String searchStr : searchStrs )
269 {
270 tmp = str.indexOf( searchStr );
271 if ( tmp == -1 )
272 {
273 continue;
274 }
275
276 if ( tmp < ret )
277 {
278 ret = tmp;
279 }
280 }
281
282 return ( ret == Integer.MAX_VALUE ) ? -1 : ret;
283 }
284
285
286
287
288
289
290
291
292
293
294
295 public static int lastIndexOfAny( String str, String... searchStrs )
296 {
297 if ( ( str == null ) || ( searchStrs == null ) )
298 {
299 return -1;
300 }
301 int ret = -1;
302 int tmp;
303 for ( String searchStr : searchStrs )
304 {
305 tmp = str.lastIndexOf( searchStr );
306 if ( tmp > ret )
307 {
308 ret = tmp;
309 }
310 }
311 return ret;
312 }
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328 public static String substring( String str, int start )
329 {
330 if ( str == null )
331 {
332 return null;
333 }
334
335
336 if ( start < 0 )
337 {
338 start = str.length() + start;
339 }
340
341 if ( start < 0 )
342 {
343 start = 0;
344 }
345 if ( start > str.length() )
346 {
347 return "";
348 }
349
350 return str.substring( start );
351 }
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366 public static String substring( String str, int start, int end )
367 {
368 if ( str == null )
369 {
370 return null;
371 }
372
373
374 if ( end < 0 )
375 {
376 end = str.length() + end;
377 }
378 if ( start < 0 )
379 {
380 start = str.length() + start;
381 }
382
383
384 if ( end > str.length() )
385 {
386
387 end = str.length();
388 }
389
390
391 if ( start > end )
392 {
393 return "";
394 }
395
396 if ( start < 0 )
397 {
398 start = 0;
399 }
400 if ( end < 0 )
401 {
402 end = 0;
403 }
404
405 return str.substring( start, end );
406 }
407
408
409
410
411
412
413
414
415
416
417
418
419
420 public static String left( String str, int len )
421 {
422 if ( len < 0 )
423 {
424 throw new IllegalArgumentException( "Requested String length " + len + " is less than zero" );
425 }
426 if ( ( str == null ) || ( str.length() <= len ) )
427 {
428 return str;
429 }
430 else
431 {
432 return str.substring( 0, len );
433 }
434 }
435
436
437
438
439
440
441
442
443
444
445
446
447
448 public static String right( String str, int len )
449 {
450 if ( len < 0 )
451 {
452 throw new IllegalArgumentException( "Requested String length " + len + " is less than zero" );
453 }
454 if ( ( str == null ) || ( str.length() <= len ) )
455 {
456 return str;
457 }
458 else
459 {
460 return str.substring( str.length() - len );
461 }
462 }
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478 public static String mid( String str, int pos, int len )
479 {
480 if ( ( pos < 0 ) || ( ( str != null ) && ( pos > str.length() ) ) )
481 {
482 throw new StringIndexOutOfBoundsException( "String index " + pos + " is out of bounds" );
483 }
484 if ( len < 0 )
485 {
486 throw new IllegalArgumentException( "Requested String length " + len + " is less than zero" );
487 }
488 if ( str == null )
489 {
490 return null;
491 }
492 if ( str.length() <= ( pos + len ) )
493 {
494 return str.substring( pos );
495 }
496 else
497 {
498 return str.substring( pos, pos + len );
499 }
500 }
501
502
503
504
505
506
507
508
509
510
511
512
513
514 @Nonnull public static String[] split( @Nonnull String str )
515 {
516 return split( str, null, -1 );
517 }
518
519
520
521
522
523
524
525 @Nonnull public static String[] split( @Nonnull String text, @Nullable String separator )
526 {
527 return split( text, separator, -1 );
528 }
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548 @Nonnull public static String[] split( @Nonnull String str, @Nullable String separator, int max )
549 {
550 StringTokenizer tok;
551 if ( separator == null )
552 {
553
554
555 tok = new StringTokenizer( str );
556 }
557 else
558 {
559 tok = new StringTokenizer( str, separator );
560 }
561
562 int listSize = tok.countTokens();
563 if ( ( max > 0 ) && ( listSize > max ) )
564 {
565 listSize = max;
566 }
567
568 String[] list = new String[listSize];
569 int i = 0;
570 int lastTokenBegin;
571 int lastTokenEnd = 0;
572 while ( tok.hasMoreTokens() )
573 {
574 if ( ( max > 0 ) && ( i == listSize - 1 ) )
575 {
576
577
578
579 String endToken = tok.nextToken();
580 lastTokenBegin = str.indexOf( endToken, lastTokenEnd );
581 list[i] = str.substring( lastTokenBegin );
582 break;
583 }
584 else
585 {
586 list[i] = tok.nextToken();
587 lastTokenBegin = str.indexOf( list[i], lastTokenEnd );
588 lastTokenEnd = lastTokenBegin + list[i].length();
589 }
590 i++;
591 }
592 return list;
593 }
594
595
596
597
598
599
600
601
602
603
604
605
606 @Nonnull public static String concatenate( @Nonnull Object... array )
607 {
608 return join( array, "" );
609 }
610
611
612
613
614
615
616
617
618
619
620
621
622 @Nonnull public static String join( @Nonnull Object[] array, @Nullable String separator )
623 {
624 if ( separator == null )
625 {
626 separator = "";
627 }
628 int arraySize = array.length;
629 int bufSize = ( arraySize == 0 ? 0 : ( array[0].toString().length() + separator.length() ) * arraySize );
630 StringBuilder buf = new StringBuilder( bufSize );
631
632 for ( int i = 0; i < arraySize; i++ )
633 {
634 if ( i > 0 )
635 {
636 buf.append( separator );
637 }
638 buf.append( array[i] );
639 }
640 return buf.toString();
641 }
642
643
644
645
646
647
648
649
650
651
652
653
654 @Nonnull public static String join( @Nonnull Iterator<?> iterator, String separator )
655 {
656 if ( separator == null )
657 {
658 separator = "";
659 }
660 StringBuilder buf = new StringBuilder( 256 );
661 while ( iterator.hasNext() )
662 {
663 buf.append( iterator.next() );
664 if ( iterator.hasNext() )
665 {
666 buf.append( separator );
667 }
668 }
669 return buf.toString();
670 }
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686 public static String replaceOnce( @Nullable String text, char repl, char with )
687 {
688 return replace( text, repl, with, 1 );
689 }
690
691
692
693
694
695
696
697
698
699
700
701
702 public static String replace( @Nullable String text, char repl, char with )
703 {
704 return replace( text, repl, with, -1 );
705 }
706
707
708
709
710
711
712
713
714
715
716
717
718
719 public static String replace( @Nullable String text, char repl, char with, int max )
720 {
721 return replace( text, String.valueOf( repl ), String.valueOf( with ), max );
722 }
723
724
725
726
727
728
729
730
731
732
733
734
735 public static String replaceOnce( @Nullable String text, @Nullable String repl, @Nullable String with )
736 {
737 return replace( text, repl, with, 1 );
738 }
739
740
741
742
743
744
745
746
747
748
749
750
751 public static String replace( @Nullable String text, @Nullable String repl, @Nullable String with )
752 {
753 return replace( text, repl, with, -1 );
754 }
755
756
757
758
759
760
761
762
763
764
765
766
767
768 public static String replace( @Nullable String text, @Nullable String repl, @Nullable String with, int max )
769 {
770 if ( ( text == null ) || ( repl == null ) || ( with == null ) || ( repl.length() == 0 ) )
771 {
772 return text;
773 }
774
775 StringBuilder buf = new StringBuilder( text.length() );
776 int start = 0, end;
777 while ( ( end = text.indexOf( repl, start ) ) != -1 )
778 {
779 buf.append( text, start, end ).append( with );
780 start = end + repl.length();
781
782 if ( --max == 0 )
783 {
784 break;
785 }
786 }
787 buf.append( text, start, text.length() );
788 return buf.toString();
789 }
790
791
792
793
794
795
796
797
798
799
800
801 @Nonnull public static String overlayString( @Nonnull String text, @Nonnull String overlay, int start, int end )
802 {
803 if ( overlay == null )
804 {
805 throw new NullPointerException( "overlay is null" );
806 }
807 return new StringBuilder( start + overlay.length() + text.length() - end + 1 )
808 .append( text, 0, start )
809 .append( overlay )
810 .append( text, end, text.length() )
811 .toString();
812 }
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828 @Nonnull public static String center( @Nonnull String str, int size )
829 {
830 return center( str, size, " " );
831 }
832
833
834
835
836
837
838
839
840
841
842
843
844
845 @Nonnull public static String center( @Nonnull String str, int size, @Nonnull String delim )
846 {
847 int sz = str.length();
848 int p = size - sz;
849 if ( p < 1 )
850 {
851 return str;
852 }
853 str = leftPad( str, sz + p / 2, delim );
854 str = rightPad( str, size, delim );
855 return str;
856 }
857
858
859
860
861
862
863
864
865
866
867
868 @Nonnull public static String chomp( @Nonnull String str )
869 {
870 return chomp( str, "\n" );
871 }
872
873
874
875
876
877
878
879
880
881
882 @Nonnull public static String chomp( @Nonnull String str, @Nonnull String sep )
883 {
884 int idx = str.lastIndexOf( sep );
885 if ( idx != -1 )
886 {
887 return str.substring( 0, idx );
888 }
889 else
890 {
891 return str;
892 }
893 }
894
895
896
897
898
899
900
901
902
903 @Nonnull public static String chompLast( @Nonnull String str )
904 {
905 return chompLast( str, "\n" );
906 }
907
908
909
910
911
912
913
914
915
916 @Nonnull public static String chompLast( @Nonnull String str, @Nonnull String sep )
917 {
918 if ( str.length() == 0 )
919 {
920 return str;
921 }
922 String sub = str.substring( str.length() - sep.length() );
923 if ( sep.equals( sub ) )
924 {
925 return str.substring( 0, str.length() - sep.length() );
926 }
927 else
928 {
929 return str;
930 }
931 }
932
933
934
935
936
937
938
939
940
941
942 @Nonnull public static String getChomp( @Nonnull String str, @Nonnull String sep )
943 {
944 int idx = str.lastIndexOf( sep );
945 if ( idx == str.length() - sep.length() )
946 {
947 return sep;
948 }
949 else if ( idx != -1 )
950 {
951 return str.substring( idx );
952 }
953 else
954 {
955 return "";
956 }
957 }
958
959
960
961
962
963
964
965
966
967
968 @Nonnull public static String prechomp( @Nonnull String str, @Nonnull String sep )
969 {
970 int idx = str.indexOf( sep );
971 if ( idx != -1 )
972 {
973 return str.substring( idx + sep.length() );
974 }
975 else
976 {
977 return str;
978 }
979 }
980
981
982
983
984
985
986
987
988
989
990 @Nonnull public static String getPrechomp( @Nonnull String str, @Nonnull String sep )
991 {
992 int idx = str.indexOf( sep );
993 if ( idx != -1 )
994 {
995 return str.substring( 0, idx + sep.length() );
996 }
997 else
998 {
999 return "";
1000 }
1001 }
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016 @Nonnull public static String chop( @Nonnull String str )
1017 {
1018 if ( "".equals( str ) )
1019 {
1020 return "";
1021 }
1022 if ( str.length() == 1 )
1023 {
1024 return "";
1025 }
1026 int lastIdx = str.length() - 1;
1027 String ret = str.substring( 0, lastIdx );
1028 char last = str.charAt( lastIdx );
1029 if ( last == '\n' )
1030 {
1031 if ( ret.charAt( lastIdx - 1 ) == '\r' )
1032 {
1033 return ret.substring( 0, lastIdx - 1 );
1034 }
1035 }
1036 return ret;
1037 }
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047 @Nonnull public static String chopNewline( @Nonnull String str )
1048 {
1049 int lastIdx = str.length() - 1;
1050 char last = str.charAt( lastIdx );
1051 if ( last == '\n' )
1052 {
1053 if ( str.charAt( lastIdx - 1 ) == '\r' )
1054 {
1055 lastIdx--;
1056 }
1057 }
1058 else
1059 {
1060 lastIdx++;
1061 }
1062 return str.substring( 0, lastIdx );
1063 }
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080 @Nonnull public static String escape( @Nonnull String str )
1081 {
1082
1083
1084 int sz = str.length();
1085 StringBuilder buffer = new StringBuilder( 2 * sz );
1086 for ( int i = 0; i < sz; i++ )
1087 {
1088 char ch = str.charAt( i );
1089
1090
1091
1092 if ( ch > 0xfff )
1093 {
1094 buffer.append( "\\u" ).append( Integer.toHexString( ch ) );
1095 }
1096 else if ( ch > 0xff )
1097 {
1098 buffer.append( "\\u0" ).append( Integer.toHexString( ch ) );
1099 }
1100 else if ( ch > 0x7f )
1101 {
1102 buffer.append( "\\u00" ).append( Integer.toHexString( ch ) );
1103 }
1104
1105 else if ( ch < 32 )
1106 {
1107 switch ( ch )
1108 {
1109 case '\b':
1110 buffer.append( '\\' );
1111 buffer.append( 'b' );
1112 break;
1113 case '\n':
1114 buffer.append( '\\' );
1115 buffer.append( 'n' );
1116 break;
1117 case '\t':
1118 buffer.append( '\\' );
1119 buffer.append( 't' );
1120 break;
1121 case '\f':
1122 buffer.append( '\\' );
1123 buffer.append( 'f' );
1124 break;
1125 case '\r':
1126 buffer.append( '\\' );
1127 buffer.append( 'r' );
1128 break;
1129 default:
1130 if ( ch > 0xf )
1131 {
1132 buffer.append( "\\u00" ).append( Integer.toHexString( ch ) );
1133 }
1134 else
1135 {
1136 buffer.append( "\\u000" ).append( Integer.toHexString( ch ) );
1137 }
1138 break;
1139 }
1140 }
1141 else
1142 {
1143 switch ( ch )
1144 {
1145 case '\'':
1146 buffer.append( '\\' );
1147 buffer.append( '\'' );
1148 break;
1149 case '"':
1150 buffer.append( '\\' );
1151 buffer.append( '"' );
1152 break;
1153 case '\\':
1154 buffer.append( '\\' );
1155 buffer.append( '\\' );
1156 break;
1157 default:
1158 buffer.append( ch );
1159 break;
1160 }
1161 }
1162 }
1163 return buffer.toString();
1164 }
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179 @Nonnull public static String repeat( @Nonnull String str, int repeat )
1180 {
1181 StringBuilder buffer = new StringBuilder( repeat * str.length() );
1182 for ( int i = 0; i < repeat; i++ )
1183 {
1184 buffer.append( str );
1185 }
1186 return buffer.toString();
1187 }
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199 @Nonnull public static String rightPad( @Nonnull String str, int size )
1200 {
1201 return rightPad( str, size, " " );
1202 }
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216 @Nonnull public static String rightPad( @Nonnull String str, int size, @Nonnull String delim )
1217 {
1218 size = ( size - str.length() ) / delim.length();
1219 if ( size > 0 )
1220 {
1221 str += repeat( delim, size );
1222 }
1223 return str;
1224 }
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236 @Nonnull public static String leftPad( @Nonnull String str, int size )
1237 {
1238 return leftPad( str, size, " " );
1239 }
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251 @Nonnull public static String leftPad( @Nonnull String str, int size, @Nonnull String delim )
1252 {
1253 size = ( size - str.length() ) / delim.length();
1254 if ( size > 0 )
1255 {
1256 str = repeat( delim, size ) + str;
1257 }
1258 return str;
1259 }
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270 public static String strip( String str )
1271 {
1272 return strip( str, null );
1273 }
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286 public static String strip( String str, @Nullable String delim )
1287 {
1288 str = stripStart( str, delim );
1289 return stripEnd( str, delim );
1290 }
1291
1292
1293
1294
1295
1296
1297
1298
1299 public static String[] stripAll( String... strs )
1300 {
1301 return stripAll( strs, null );
1302 }
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312 public static String[] stripAll( String[] strs, @Nullable String delimiter )
1313 {
1314 if ( ( strs == null ) || ( strs.length == 0 ) )
1315 {
1316 return strs;
1317 }
1318 int sz = strs.length;
1319 String[] newArr = new String[sz];
1320 for ( int i = 0; i < sz; i++ )
1321 {
1322 newArr[i] = strip( strs[i], delimiter );
1323 }
1324 return newArr;
1325 }
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337 public static String stripEnd( String str, @Nullable String strip )
1338 {
1339 if ( str == null )
1340 {
1341 return null;
1342 }
1343 int end = str.length();
1344
1345 if ( strip == null )
1346 {
1347 while ( ( end != 0 ) && Character.isWhitespace( str.charAt( end - 1 ) ) )
1348 {
1349 end--;
1350 }
1351 }
1352 else
1353 {
1354 while ( ( end != 0 ) && ( strip.indexOf( str.charAt( end - 1 ) ) != -1 ) )
1355 {
1356 end--;
1357 }
1358 }
1359 return str.substring( 0, end );
1360 }
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372 public static String stripStart( String str, @Nullable String strip )
1373 {
1374 if ( str == null )
1375 {
1376 return null;
1377 }
1378
1379 int start = 0;
1380
1381 int sz = str.length();
1382
1383 if ( strip == null )
1384 {
1385 while ( ( start != sz ) && Character.isWhitespace( str.charAt( start ) ) )
1386 {
1387 start++;
1388 }
1389 }
1390 else
1391 {
1392 while ( ( start != sz ) && ( strip.indexOf( str.charAt( start ) ) != -1 ) )
1393 {
1394 start++;
1395 }
1396 }
1397 return str.substring( start );
1398 }
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410 public static String upperCase( String str )
1411 {
1412 if ( str == null )
1413 {
1414 return null;
1415 }
1416 return str.toUpperCase();
1417 }
1418
1419
1420
1421
1422
1423
1424
1425
1426 public static String lowerCase( String str )
1427 {
1428 if ( str == null )
1429 {
1430 return null;
1431 }
1432 return str.toLowerCase();
1433 }
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444 public static String uncapitalise( String str )
1445 {
1446 if ( str == null )
1447 {
1448 return null;
1449 }
1450 else
1451 {
1452 int length = str.length();
1453 if ( length == 0 )
1454 {
1455 return "";
1456 }
1457 else
1458 {
1459 return new StringBuffer( length )
1460 .append( Character.toLowerCase( str.charAt( 0 ) ) )
1461 .append( str, 1, length )
1462 .toString();
1463 }
1464 }
1465 }
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476 public static String capitalise( String str )
1477 {
1478 if ( str == null )
1479 {
1480 return null;
1481 }
1482 else
1483 {
1484 int length = str.length();
1485 if ( length == 0 )
1486 {
1487 return "";
1488 }
1489 else
1490 {
1491 return new StringBuilder( length )
1492 .append( Character.toTitleCase( str.charAt( 0 ) ) )
1493 .append( str, 1, length )
1494 .toString();
1495 }
1496 }
1497 }
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510 public static String swapCase( String str )
1511 {
1512 if ( str == null )
1513 {
1514 return null;
1515 }
1516 int sz = str.length();
1517 StringBuilder buffer = new StringBuilder( sz );
1518
1519 boolean whitespace = false;
1520 char ch;
1521 char tmp;
1522
1523 for ( int i = 0; i < sz; i++ )
1524 {
1525 ch = str.charAt( i );
1526 if ( Character.isUpperCase( ch ) )
1527 {
1528 tmp = Character.toLowerCase( ch );
1529 }
1530 else if ( Character.isTitleCase( ch ) )
1531 {
1532 tmp = Character.toLowerCase( ch );
1533 }
1534 else if ( Character.isLowerCase( ch ) )
1535 {
1536 if ( whitespace )
1537 {
1538 tmp = Character.toTitleCase( ch );
1539 }
1540 else
1541 {
1542 tmp = Character.toUpperCase( ch );
1543 }
1544 }
1545 else
1546 {
1547 tmp = ch;
1548 }
1549 buffer.append( tmp );
1550 whitespace = Character.isWhitespace( ch );
1551 }
1552 return buffer.toString();
1553 }
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567 public static String capitaliseAllWords( String str )
1568 {
1569 if ( str == null )
1570 {
1571 return null;
1572 }
1573 int sz = str.length();
1574 StringBuilder buffer = new StringBuilder( sz );
1575 boolean space = true;
1576 for ( int i = 0; i < sz; i++ )
1577 {
1578 char ch = str.charAt( i );
1579 if ( Character.isWhitespace( ch ) )
1580 {
1581 buffer.append( ch );
1582 space = true;
1583 }
1584 else if ( space )
1585 {
1586 buffer.append( Character.toTitleCase( ch ) );
1587 space = false;
1588 }
1589 else
1590 {
1591 buffer.append( ch );
1592 }
1593 }
1594 return buffer.toString();
1595 }
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608 public static String uncapitaliseAllWords( String str )
1609 {
1610 if ( str == null )
1611 {
1612 return null;
1613 }
1614 int sz = str.length();
1615 StringBuilder buffer = new StringBuilder( sz );
1616 boolean space = true;
1617 for ( int i = 0; i < sz; i++ )
1618 {
1619 char ch = str.charAt( i );
1620 if ( Character.isWhitespace( ch ) )
1621 {
1622 buffer.append( ch );
1623 space = true;
1624 }
1625 else if ( space )
1626 {
1627 buffer.append( Character.toLowerCase( ch ) );
1628 space = false;
1629 }
1630 else
1631 {
1632 buffer.append( ch );
1633 }
1634 }
1635 return buffer.toString();
1636 }
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653 public static String getNestedString( String str, @Nonnull String tag )
1654 {
1655 return getNestedString( str, tag, tag );
1656 }
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667 public static String getNestedString( String str, @Nonnull String open, @Nonnull String close )
1668 {
1669 if ( str == null )
1670 {
1671 return null;
1672 }
1673 int start = str.indexOf( open );
1674 if ( start != -1 )
1675 {
1676 int end = str.indexOf( close, start + open.length() );
1677 if ( end != -1 )
1678 {
1679 return str.substring( start + open.length(), end );
1680 }
1681 }
1682 return null;
1683 }
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695 public static int countMatches( @Nullable String str, @Nonnull String sub )
1696 {
1697 if ( sub.equals( "" ) )
1698 {
1699 return 0;
1700 }
1701 if ( str == null )
1702 {
1703 return 0;
1704 }
1705 int count = 0;
1706 int idx = 0;
1707 while ( ( idx = str.indexOf( sub, idx ) ) != -1 )
1708 {
1709 count++;
1710 idx += sub.length();
1711 }
1712 return count;
1713 }
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727 public static boolean isAlpha( String str )
1728 {
1729 if ( str == null )
1730 {
1731 return false;
1732 }
1733 int sz = str.length();
1734 for ( int i = 0; i < sz; i++ )
1735 {
1736 if ( !Character.isLetter( str.charAt( i ) ) )
1737 {
1738 return false;
1739 }
1740 }
1741 return true;
1742 }
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753 public static boolean isWhitespace( String str )
1754 {
1755 if ( str == null )
1756 {
1757 return false;
1758 }
1759 int sz = str.length();
1760 for ( int i = 0; i < sz; i++ )
1761 {
1762 if ( ( !Character.isWhitespace( str.charAt( i ) ) ) )
1763 {
1764 return false;
1765 }
1766 }
1767 return true;
1768 }
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781 public static boolean isAlphaSpace( String str )
1782 {
1783 if ( str == null )
1784 {
1785 return false;
1786 }
1787 int sz = str.length();
1788 for ( int i = 0; i < sz; i++ )
1789 {
1790 if ( ( !Character.isLetter( str.charAt( i ) ) ) && ( str.charAt( i ) != ' ' ) )
1791 {
1792 return false;
1793 }
1794 }
1795 return true;
1796 }
1797
1798
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808 public static boolean isAlphanumeric( String str )
1809 {
1810 if ( str == null )
1811 {
1812 return false;
1813 }
1814 int sz = str.length();
1815 for ( int i = 0; i < sz; i++ )
1816 {
1817 if ( !Character.isLetterOrDigit( str.charAt( i ) ) )
1818 {
1819 return false;
1820 }
1821 }
1822 return true;
1823 }
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836 public static boolean isAlphanumericSpace( String str )
1837 {
1838 if ( str == null )
1839 {
1840 return false;
1841 }
1842 int sz = str.length();
1843 for ( int i = 0; i < sz; i++ )
1844 {
1845 if ( ( !Character.isLetterOrDigit( str.charAt( i ) ) ) && ( str.charAt( i ) != ' ' ) )
1846 {
1847 return false;
1848 }
1849 }
1850 return true;
1851 }
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862 public static boolean isNumeric( String str )
1863 {
1864 if ( str == null )
1865 {
1866 return false;
1867 }
1868 int sz = str.length();
1869 for ( int i = 0; i < sz; i++ )
1870 {
1871 if ( !Character.isDigit( str.charAt( i ) ) )
1872 {
1873 return false;
1874 }
1875 }
1876 return true;
1877 }
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892 @Deprecated
1893 @Nonnull public static String defaultString( Object obj )
1894 {
1895 return defaultString( obj, "" );
1896 }
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910 @Deprecated
1911 @Nonnull public static String defaultString( Object obj, @Nonnull String defaultString )
1912 {
1913 return ( obj == null ) ? defaultString : obj.toString();
1914 }
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927 public static String reverse( String str )
1928 {
1929 if ( str == null )
1930 {
1931 return null;
1932 }
1933 return new StringBuffer( str ).reverse().toString();
1934 }
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947 @Nonnull public static String reverseDelimitedString( @Nonnull String str, String delimiter )
1948 {
1949
1950
1951 String[] strs = split( str, delimiter );
1952 reverseArray( strs );
1953 return join( strs, delimiter );
1954 }
1955
1956
1957
1958
1959
1960
1961 private static void reverseArray( @Nonnull String... array )
1962 {
1963 int i = 0;
1964 int j = array.length - 1;
1965 String tmp;
1966
1967 while ( j > i )
1968 {
1969 tmp = array[j];
1970 array[j] = array[i];
1971 array[i] = tmp;
1972 j--;
1973 i++;
1974 }
1975 }
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992 @Nonnull public static String abbreviate( @Nonnull String s, int maxWidth )
1993 {
1994 return abbreviate( s, 0, maxWidth );
1995 }
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012 @Nonnull public static String abbreviate( @Nonnull String s, int offset, int maxWidth )
2013 {
2014 if ( maxWidth < 4 )
2015 {
2016 throw new IllegalArgumentException( "Minimum abbreviation width is 4" );
2017 }
2018 if ( s.length() <= maxWidth )
2019 {
2020 return s;
2021 }
2022 if ( offset > s.length() )
2023 {
2024 offset = s.length();
2025 }
2026 if ( ( s.length() - offset ) < ( maxWidth - 3 ) )
2027 {
2028 offset = s.length() - ( maxWidth - 3 );
2029 }
2030 if ( offset <= 4 )
2031 {
2032 return s.substring( 0, maxWidth - 3 ) + "...";
2033 }
2034 if ( maxWidth < 7 )
2035 {
2036 throw new IllegalArgumentException( "Minimum abbreviation width with offset is 7" );
2037 }
2038 if ( ( offset + ( maxWidth - 3 ) ) < s.length() )
2039 {
2040 return "..." + abbreviate( s.substring( offset ), maxWidth - 3 );
2041 }
2042 return "..." + s.substring( s.length() - ( maxWidth - 3 ) );
2043 }
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060 public static String difference( @Nonnull String s1, @Nonnull String s2 )
2061 {
2062 int at = differenceAt( s1, s2 );
2063 if ( at == -1 )
2064 {
2065 return "";
2066 }
2067 return s2.substring( at );
2068 }
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080 public static int differenceAt( @Nonnull String s1, @Nonnull String s2 )
2081 {
2082 int i;
2083 for ( i = 0; ( i < s1.length() ) && ( i < s2.length() ); ++i )
2084 {
2085 if ( s1.charAt( i ) != s2.charAt( i ) )
2086 {
2087 break;
2088 }
2089 }
2090 if ( ( i < s2.length() ) || ( i < s1.length() ) )
2091 {
2092 return i;
2093 }
2094 return -1;
2095 }
2096
2097
2098
2099
2100
2101
2102
2103
2104
2105
2106 public static String interpolate( String text, @Nonnull Map<?, ?> namespace )
2107 {
2108 for ( Map.Entry<?, ?> entry : namespace.entrySet() )
2109 {
2110 String key = entry.getKey().toString();
2111
2112 Object obj = entry.getValue();
2113
2114 if ( obj == null )
2115 {
2116 throw new NullPointerException( "The value of the key '" + key + "' is null." );
2117 }
2118
2119 String value = obj.toString();
2120
2121 text = replace( text, "${" + key + "}", value );
2122
2123 if ( !key.contains( " " ) )
2124 {
2125 text = replace( text, "$" + key, value );
2126 }
2127 }
2128 return text;
2129 }
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144 @Nonnull public static String removeAndHump( @Nonnull String data, @Nonnull String replaceThis )
2145 {
2146 String temp;
2147
2148 StringBuilder out = new StringBuilder();
2149
2150 temp = data;
2151
2152 StringTokenizer st = new StringTokenizer( temp, replaceThis );
2153
2154 while ( st.hasMoreTokens() )
2155 {
2156 String element = st.nextToken();
2157
2158 out.append( capitalizeFirstLetter( element ) );
2159 }
2160
2161 return out.toString();
2162 }
2163
2164
2165
2166
2167
2168
2169
2170
2171
2172
2173 @Nonnull public static String capitalizeFirstLetter( @Nonnull String data )
2174 {
2175 char firstChar = data.charAt( 0 );
2176 char titleCase = Character.toTitleCase( firstChar );
2177 if ( firstChar == titleCase )
2178 {
2179 return data;
2180 }
2181 StringBuilder result = new StringBuilder( data.length() );
2182 result.append( titleCase );
2183 result.append( data, 1, data.length() );
2184 return result.toString();
2185 }
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196 @Nonnull public static String lowercaseFirstLetter( @Nonnull String data )
2197 {
2198 char firstLetter = Character.toLowerCase( data.substring( 0, 1 ).charAt( 0 ) );
2199
2200 String restLetters = data.substring( 1 );
2201
2202 return firstLetter + restLetters;
2203 }
2204
2205
2206
2207
2208
2209
2210
2211
2212 @Nonnull public static String addAndDeHump( @Nonnull String view )
2213 {
2214 StringBuilder sb = new StringBuilder();
2215
2216 for ( int i = 0; i < view.length(); i++ )
2217 {
2218 if ( ( i != 0 ) && Character.isUpperCase( view.charAt( i ) ) )
2219 {
2220 sb.append( '-' );
2221 }
2222
2223 sb.append( view.charAt( i ) );
2224 }
2225
2226 return sb.toString().trim().toLowerCase( Locale.ENGLISH );
2227 }
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247 public static String quoteAndEscape( @Nullable String source, char quoteChar )
2248 {
2249 return quoteAndEscape( source, quoteChar, new char[]{ quoteChar }, new char[]{ ' ' }, '\\', false );
2250 }
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262 public static String quoteAndEscape( @Nullable String source, char quoteChar, @Nonnull char[] quotingTriggers )
2263 {
2264 return quoteAndEscape( source, quoteChar, new char[]{ quoteChar }, quotingTriggers, '\\', false );
2265 }
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277 public static String quoteAndEscape( @Nullable String source, char quoteChar,
2278 @Nonnull final char[] escapedChars, char escapeChar, boolean force )
2279 {
2280 return quoteAndEscape( source, quoteChar, escapedChars, new char[]{ ' ' }, escapeChar, force );
2281 }
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292 public static String quoteAndEscape( @Nullable String source, char quoteChar, @Nonnull final char[] escapedChars,
2293 @Nonnull final char[] quotingTriggers, char escapeChar, boolean force )
2294 {
2295 if ( source == null )
2296 {
2297 return null;
2298 }
2299
2300 if ( !force && source.startsWith( Character.toString( quoteChar ) ) && source.endsWith(
2301 Character.toString( quoteChar ) ) )
2302 {
2303 return source;
2304 }
2305
2306 String escaped = escape( source, escapedChars, escapeChar );
2307
2308 boolean quote = false;
2309 if ( force )
2310 {
2311 quote = true;
2312 }
2313 else if ( !escaped.equals( source ) )
2314 {
2315 quote = true;
2316 }
2317 else
2318 {
2319 for ( char quotingTrigger : quotingTriggers )
2320 {
2321 if ( escaped.indexOf( quotingTrigger ) > -1 )
2322 {
2323 quote = true;
2324 break;
2325 }
2326 }
2327 }
2328
2329 if ( quote )
2330 {
2331 return quoteChar + escaped + quoteChar;
2332 }
2333
2334 return escaped;
2335 }
2336
2337
2338
2339
2340
2341
2342
2343 public static String escape( @Nullable String source, @Nonnull final char[] escapedChars, char escapeChar )
2344 {
2345 if ( source == null )
2346 {
2347 return null;
2348 }
2349
2350 char[] eqc = new char[escapedChars.length];
2351 System.arraycopy( escapedChars, 0, eqc, 0, escapedChars.length );
2352 Arrays.sort( eqc );
2353
2354 StringBuilder buffer = new StringBuilder( source.length() );
2355
2356 for ( int i = 0; i < source.length(); i++ )
2357 {
2358 final char c = source.charAt( i );
2359 int result = Arrays.binarySearch( eqc, c );
2360
2361 if ( result > -1 )
2362 {
2363 buffer.append( escapeChar );
2364 }
2365 buffer.append( c );
2366 }
2367
2368 return buffer.toString();
2369 }
2370
2371
2372
2373
2374
2375
2376
2377
2378 @Nonnull public static String removeDuplicateWhitespace( @Nonnull String s )
2379 {
2380 StringBuilder result = new StringBuilder();
2381 int length = s.length();
2382 boolean isPreviousWhiteSpace = false;
2383 for ( int i = 0; i < length; i++ )
2384 {
2385 char c = s.charAt( i );
2386 boolean thisCharWhiteSpace = Character.isWhitespace( c );
2387 if ( !( isPreviousWhiteSpace && thisCharWhiteSpace ) )
2388 {
2389 result.append( c );
2390 }
2391 isPreviousWhiteSpace = thisCharWhiteSpace;
2392 }
2393 return result.toString();
2394 }
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405
2406
2407
2408 @Deprecated
2409 public static String unifyLineSeparators( @Nullable String s )
2410 {
2411 return unifyLineSeparators( s, System.getProperty( "line.separator" ) );
2412 }
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424 public static String unifyLineSeparators( @Nullable String s, @Nullable String ls )
2425 {
2426 if ( s == null )
2427 {
2428 return null;
2429 }
2430
2431 if ( ls == null )
2432 {
2433 ls = System.getProperty( "line.separator" );
2434 }
2435
2436 if ( !( ls.equals( "\n" ) || ls.equals( "\r" ) || ls.equals( "\r\n" ) ) )
2437 {
2438 throw new IllegalArgumentException( "Requested line separator is invalid." );
2439 }
2440
2441 int length = s.length();
2442
2443 StringBuilder buffer = new StringBuilder( length );
2444 for ( int i = 0; i < length; i++ )
2445 {
2446 if ( s.charAt( i ) == '\r' )
2447 {
2448 if ( ( i + 1 ) < length && s.charAt( i + 1 ) == '\n' )
2449 {
2450 i++;
2451 }
2452
2453 buffer.append( ls );
2454 }
2455 else if ( s.charAt( i ) == '\n' )
2456 {
2457 buffer.append( ls );
2458 }
2459 else
2460 {
2461 buffer.append( s.charAt( i ) );
2462 }
2463 }
2464
2465 return buffer.toString();
2466 }
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487 public static boolean contains( @Nullable String str, char searchChar )
2488 {
2489 return !isEmpty( str ) && str.indexOf( searchChar ) >= 0;
2490 }
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512 public static boolean contains( @Nullable String str, @Nullable String searchStr )
2513 {
2514 return !( str == null || searchStr == null ) && str.contains( searchStr );
2515 }
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536 public static boolean endsWithIgnoreCase( @Nullable String str, @Nullable String searchStr )
2537 {
2538 if ( str == null || searchStr == null )
2539 {
2540
2541 return false;
2542 }
2543
2544 if ( str.length() < searchStr.length() )
2545 {
2546 return false;
2547 }
2548
2549 return str.regionMatches( true, str.length() - searchStr.length(), searchStr, 0, searchStr.length() );
2550 }
2551 }