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