001 package railo.commons.lang; 002 003 import java.io.UnsupportedEncodingException; 004 import java.util.HashMap; 005 import java.util.Iterator; 006 import java.util.Map; 007 008 import railo.commons.io.SystemUtil; 009 import railo.runtime.exp.PageException; 010 import railo.runtime.op.Caster; 011 import railo.runtime.type.Collection; 012 import railo.runtime.type.util.ArrayUtil; 013 014 015 016 017 018 /** 019 * Util to do some additional String Operations 020 */ 021 public final class StringUtil { 022 023 /** 024 * do first Letter Upper case 025 * @param str String to operate 026 * @return uppercase string 027 */ 028 public static String ucFirst(String str) { 029 if(str==null) return null; 030 else if(str.length()<=1) return str.toUpperCase(); 031 else { 032 return str.substring(0,1).toUpperCase()+str.substring(1); 033 } 034 } 035 036 037 public static String capitalize( String input, char[] delims ) { 038 039 if (isEmpty(input)) return input; 040 041 if (ArrayUtil.isEmpty(delims)) 042 delims = new char[]{ '.', '-', '(', ')' }; 043 044 StringBuilder sb = new StringBuilder( input.length() ); 045 046 boolean isLastDelim = true,isLastSpace = true; 047 int len=input.length(); 048 for (int i=0; i<len; i++) { 049 050 char c = input.charAt( i ); 051 052 if ( Character.isWhitespace(c) ) { 053 054 if ( !isLastSpace ) 055 sb.append( ' ' ); 056 057 isLastSpace = true; 058 } 059 else { 060 061 sb.append( ( isLastSpace || isLastDelim ) ? Character.toUpperCase( c ) : c ); 062 063 isLastDelim = _contains(delims, c ); 064 isLastSpace = false; 065 } 066 } 067 068 return sb.toString(); 069 } 070 071 072 private static boolean _contains(char[] chars, char c) { 073 for ( int i=0; i<chars.length; i++ ) { 074 if(chars[i]==c) return true; 075 } 076 return false; 077 } 078 079 080 /** 081 * do first Letter Upper case 082 * @param str String to operate 083 * @return lower case String 084 */ 085 public static String lcFirst(String str) { 086 if(str==null) return null; 087 else if(str.length()<=1) return str.toLowerCase(); 088 else { 089 return str.substring(0,1).toLowerCase()+str.substring(1); 090 } 091 } 092 093 /** 094 * Unescapes HTML Tags 095 * @param html html code to escape 096 * @return escaped html code 097 */ 098 public static String unescapeHTML(String html) { 099 return HTMLEntities.unescapeHTML(html); 100 } 101 102 /** 103 * Escapes XML Tags 104 * @param html html code to unescape 105 * @return unescaped html code 106 */ 107 public static String escapeHTML(String html) { 108 return HTMLEntities.escapeHTML(html); 109 } 110 111 /** 112 * escapes JS sensitive characters 113 * @param str String to escape 114 * @return escapes String 115 */ 116 public static String escapeJS(String str) { 117 char[] arr=str.toCharArray(); 118 StringBuilder rtn=new StringBuilder(arr.length); 119 for(int i=0;i<arr.length;i++) { 120 switch(arr[i]) { 121 case '\\': rtn.append("\\\\"); break; 122 case '\n': rtn.append("\\n"); break; 123 case '\r': rtn.append("\\r"); break; 124 case '\f': rtn.append("\\f"); break; 125 case '\b': rtn.append("\\b"); break; 126 case '\t': rtn.append("\\t"); break; 127 case '"' : rtn.append("\\\""); break; 128 case '\'': rtn.append("\\\'"); break; 129 default : rtn.append(arr[i]); break; 130 } 131 } 132 return rtn.toString(); 133 } 134 135 /** 136 * reapeats a string 137 * @param str string to repeat 138 * @param count how many time string will be reapeted 139 * @return reapted string 140 */ 141 public static String repeatString(String str,int count) { 142 if(count<=0) return ""; 143 char[] chars = str.toCharArray(); 144 char[] rtn=new char[chars.length*count]; 145 int pos=0; 146 for(int i=0;i<count;i++) { 147 for(int y=0;y<chars.length;y++)rtn[pos++]=chars[y]; 148 //rtn.append(str); 149 } 150 return new String(rtn); 151 } 152 153 /** 154 * translate, like method toString, a object to a string, but when value is null value will be translated to a empty String (""). 155 * @param o Object to convert 156 * @return converted String 157 */ 158 public static String toStringEmptyIfNull(Object o) { 159 if(o==null)return ""; 160 return o.toString(); 161 } 162 163 public static String emptyIfNull(String str) { 164 if(str==null)return ""; 165 return str; 166 } 167 168 public static String emptyIfNull(Collection.Key key) { 169 if(key==null)return ""; 170 return key.getString(); 171 } 172 173 /** 174 * escape all special characters of the regular expresson language 175 * @param str String to escape 176 * @return escaped String 177 */ 178 public static String reqExpEscape(String str) { 179 char[] arr = str.toCharArray(); 180 StringBuilder sb=new StringBuilder(str.length()*2); 181 182 for(int i=0;i<arr.length;i++) { 183 sb.append('\\'); 184 sb.append(arr[i]); 185 } 186 187 return sb.toString(); 188 } 189 190 /** 191 * translate a string to a valid identity variable name 192 * @param varName variable name template to translate 193 * @return translated variable name 194 */ 195 public static String toIdentityVariableName(String varName) { 196 char[] chars=varName.toCharArray(); 197 long changes=0; 198 199 StringBuilder rtn=new StringBuilder(chars.length+2); 200 rtn.append("CF"); 201 202 for(int i=0;i<chars.length;i++) { 203 char c=chars[i]; 204 if((c>='a' && c<='z') ||(c>='A' && c<='Z') ||(c>='0' && c<='9')) 205 rtn.append(c); 206 else { 207 rtn.append('_'); 208 changes+=(c*(i+1)); 209 } 210 } 211 212 return rtn.append(changes).toString(); 213 } 214 /** 215 * translate a string to a valid classname string 216 * @param str string to translate 217 * @return translated String 218 */ 219 public static String toClassName(String str) { 220 StringBuilder rtn=new StringBuilder(); 221 String[] arr=str.split("[\\\\|//]"); 222 for(int i=0;i<arr.length;i++) { 223 if(arr[i].length()==0)continue; 224 if(rtn.length()!=0)rtn.append('.'); 225 char[] chars=arr[i].toCharArray(); 226 long changes=0; 227 for(int y=0;y<chars.length;y++) { 228 char c=chars[y]; 229 if(y==0 && (c>='0' && c<='9'))rtn.append("_"+c); 230 else if((c>='a' && c<='z') ||(c>='A' && c<='Z') ||(c>='0' && c<='9')) 231 rtn.append(c); 232 else { 233 rtn.append('_'); 234 changes+=(c*(i+1)); 235 } 236 } 237 if(changes>0)rtn.append(changes); 238 } 239 return rtn.toString(); 240 } 241 242 /** 243 * translate a string to a valid variable string 244 * @param str string to translate 245 * @return translated String 246 */ 247 248 public static String toVariableName(String str) { 249 return toVariableName(str, true); 250 } 251 public static String toVariableName(String str, boolean addIdentityNumber) { 252 253 StringBuilder rtn=new StringBuilder(); 254 char[] chars=str.toCharArray(); 255 long changes=0; 256 boolean doCorrect=true; 257 for(int i=0;i<chars.length;i++) { 258 char c=chars[i]; 259 if(i==0 && (c>='0' && c<='9'))rtn.append("_"+c); 260 else if((c>='a' && c<='z') ||(c>='A' && c<='Z') ||(c>='0' && c<='9') || c=='_' || c=='$') 261 rtn.append(c); 262 else { 263 doCorrect=false; 264 rtn.append('_'); 265 changes+=(c*(i+1)); 266 } 267 } 268 269 if(addIdentityNumber && changes>0)rtn.append(changes); 270 //print.ln(" - "+rtn); 271 272 if(doCorrect)return correctReservedWord(rtn.toString()); 273 return rtn.toString(); 274 } 275 276 277 /** 278 * if given string is a keyword it will be replaced with none keyword 279 * @param str 280 * @return corrected word 281 */ 282 private static String correctReservedWord(String str) { 283 char first=str.charAt(0); 284 285 switch(first) { 286 case 'a': 287 if(str.equals("abstract")) return "_"+str; 288 break; 289 case 'b': 290 if(str.equals("boolean")) return "_"+str; 291 else if(str.equals("break")) return "_"+str; 292 else if(str.equals("byte")) return "_"+str; 293 break; 294 case 'c': 295 if(str.equals("case")) return "_"+str; 296 else if(str.equals("catch")) return "_"+str; 297 else if(str.equals("char")) return "_"+str; 298 else if(str.equals("const")) return "_"+str; 299 else if(str.equals("class")) return "_"+str; 300 else if(str.equals("continue")) return "_"+str; 301 break; 302 case 'd': 303 if(str.equals("default")) return "_"+str; 304 else if(str.equals("do")) return "_"+str; 305 else if(str.equals("double")) return "_"+str; 306 break; 307 case 'e': 308 if(str.equals("else")) return "_"+str; 309 else if(str.equals("extends")) return "_"+str; 310 else if(str.equals("enum")) return "_"+str; 311 break; 312 case 'f': 313 if(str.equals("false")) return "_"+str; 314 else if(str.equals("final")) return "_"+str; 315 else if(str.equals("finally")) return "_"+str; 316 else if(str.equals("float")) return "_"+str; 317 else if(str.equals("for")) return "_"+str; 318 break; 319 case 'g': 320 if(str.equals("goto")) return "_"+str; 321 break; 322 case 'i': 323 if(str.equals("if")) return "_"+str; 324 else if(str.equals("implements")) return "_"+str; 325 else if(str.equals("import")) return "_"+str; 326 else if(str.equals("instanceof")) return "_"+str; 327 else if(str.equals("int")) return "_"+str; 328 else if(str.equals("interface")) return "_"+str; 329 break; 330 case 'n': 331 if(str.equals("native")) return "_"+str; 332 else if(str.equals("new")) return "_"+str; 333 else if(str.equals("null")) return "_"+str; 334 break; 335 case 'p': 336 if(str.equals("package")) return "_"+str; 337 else if(str.equals("private")) return "_"+str; 338 else if(str.equals("protected")) return "_"+str; 339 else if(str.equals("public")) return "_"+str; 340 break; 341 case 'r': 342 if(str.equals("return")) return "_"+str; 343 break; 344 case 's': 345 if(str.equals("short")) return "_"+str; 346 else if(str.equals("static")) return "_"+str; 347 else if(str.equals("strictfp")) return "_"+str; 348 else if(str.equals("super")) return "_"+str; 349 else if(str.equals("switch")) return "_"+str; 350 else if(str.equals("synchronized")) return "_"+str; 351 break; 352 case 't': 353 if(str.equals("this")) return "_"+str; 354 else if(str.equals("throw")) return "_"+str; 355 else if(str.equals("throws")) return "_"+str; 356 else if(str.equals("transient")) return "_"+str; 357 else if(str.equals("true")) return "_"+str; 358 else if(str.equals("try")) return "_"+str; 359 break; 360 case 'v': 361 if(str.equals("void")) return "_"+str; 362 else if(str.equals("volatile")) return "_"+str; 363 break; 364 case 'w': 365 if(str.equals("while")) return "_"+str; 366 break; 367 } 368 return str; 369 370 } 371 372 /** 373 * This function returns a string with whitespace stripped from the beginning of str 374 * @param str String to clean 375 * @return cleaned String 376 */ 377 public static String ltrim(String str,String defaultValue) { 378 if(str==null) return defaultValue; 379 int len = str.length(); 380 int st = 0; 381 382 while ((st < len) && (str.charAt(st) <= ' ')) { 383 st++; 384 } 385 return ((st > 0)) ? str.substring(st) : str; 386 } 387 388 /** 389 * This function returns a string with whitespace stripped from the end of str 390 * @param str String to clean 391 * @return cleaned String 392 */ 393 public static String rtrim(String str,String defaultValue) { 394 if(str==null) return defaultValue; 395 int len = str.length(); 396 397 while ((0 < len) && (str.charAt(len-1) <= ' ')) { 398 len--; 399 } 400 return (len < str.length()) ? str.substring(0, len) : str; 401 } 402 403 404 405 /** 406 * return if in a string are line feeds or not 407 * @param str string to check 408 * @return translated string 409 */ 410 public static boolean hasLineFeed(String str) { 411 int len=str.length(); 412 char c; 413 for(int i=0;i<len;i++) { 414 c=str.charAt(i); 415 if(c=='\n' || c=='\r') return true; 416 } 417 return false; 418 } 419 420 /** 421 * remove all white spaces followd by whitespaces 422 * @param str strring to translate 423 * @return translated string 424 */ 425 public static String suppressWhiteSpace(String str) { 426 int len=str.length(); 427 StringBuilder sb=new StringBuilder(len); 428 //boolean wasWS=false; 429 430 char c; 431 char buffer=0; 432 for(int i=0;i<len;i++) { 433 c=str.charAt(i); 434 if(c=='\n' || c=='\r') buffer='\n'; 435 else if(c==' ' || c=='\t') { 436 if(buffer==0)buffer=c; 437 } 438 else { 439 if(buffer!=0){ 440 sb.append(buffer); 441 buffer=0; 442 } 443 sb.append(c); 444 } 445 //sb.append(c); 446 } 447 if(buffer!=0)sb.append(buffer); 448 449 return sb.toString(); 450 } 451 452 453 454 /** 455 * returns string, if given string is null or lengt 0 return default value 456 * @param value 457 * @param defaultValue 458 * @return value or default value 459 */ 460 public static String toString(String value, String defaultValue) { 461 return value==null || value.length()==0?defaultValue:value; 462 } 463 464 /** 465 * returns string, if given string is null or lengt 0 return default value 466 * @param value 467 * @param defaultValue 468 * @return value or default value 469 */ 470 public static String toString(Object value, String defaultValue) { 471 if(value==null) return defaultValue; 472 return toString(value.toString(), defaultValue); 473 } 474 475 /** 476 * cut string to max size if the string is greater, otherweise to nothing 477 * @param content 478 * @param max 479 * @return cutted string 480 */ 481 482 public static String max(String content,int max) { 483 return max(content, max,""); 484 } 485 486 public static String max(String content,int max, String dotDotDot) { 487 if(content==null) return null; 488 if(content.length()<=max) return content; 489 490 return content.substring(0,max)+dotDotDot; 491 } 492 493 494 /** 495 * performs a replace operation on a string 496 * 497 * @param input - the string input to work on 498 * @param find - the substring to find 499 * @param repl - the substring to replace the matches with 500 * @param firstOnly - if true then only the first occurrence of {@code find} will be replaced 501 * @param ignoreCase - if true then matches will not be case sensitive 502 * @return 503 */ 504 public static String replace( String input, String find, String repl, boolean firstOnly, boolean ignoreCase ) { 505 506 String scan = input; 507 int findLen = find.length(); 508 509 if ( ignoreCase ) { 510 511 scan = scan.toLowerCase(); 512 find = find.toLowerCase(); 513 } else if ( findLen == repl.length() ) { 514 515 if ( find.equals( repl ) ) 516 return input; 517 518 if ( !firstOnly && findLen == 1 ) 519 return input.replace( find.charAt(0), repl.charAt(0) ); 520 } 521 522 StringBuilder sb = new StringBuilder( repl.length() > find.length() ? (int)Math.ceil( input.length() * 1.2 ) : input.length() ); 523 524 int start = 0; 525 int pos; 526 527 while ( (pos = scan.indexOf( find, start ) ) != -1 ) { 528 529 sb.append( input.substring( start, pos ) ); 530 sb.append( repl ); 531 532 start = pos + findLen; 533 534 if ( firstOnly ) 535 break; 536 } 537 538 if ( input.length() > start ) 539 sb.append( input.substring( start ) ); 540 541 return sb.toString(); 542 } 543 544 545 /** 546 * maintains the legacy signature of this method where matches are CaSe sensitive (sets the default of ignoreCase to false). 547 * 548 * @param input - the string input to work on 549 * @param find - the substring to find 550 * @param repl - the substring to replace the matches with 551 * @param firstOnly - if true then only the first occurrence of {@code find} will be replaced 552 * @return - calls replace( input, find, repl, firstOnly, false ) 553 */ 554 public static String replace( String input, String find, String repl, boolean firstOnly ) { 555 556 return replace( input, find, repl, firstOnly, false ); 557 } 558 559 560 /** 561 * performs a CaSe sensitive replace all 562 * 563 * @param input - the string input to work on 564 * @param find - the substring to find 565 * @param repl - the substring to replace the matches with 566 * @return - calls replace( input, find, repl, false, false ) 567 */ 568 public static String replace( String input, String find, String repl ) { 569 570 return replace( input, find, repl, false, false ); 571 } 572 573 574 /** 575 * adds zeros add the begin of a int example: addZeros(2,3) return "002" 576 * @param i number to add nulls 577 * @param size 578 * @return min len of return value; 579 */ 580 public static String addZeros(int i, int size) { 581 String rtn=Caster.toString(i); 582 if(rtn.length()<size) return repeatString("0",size-rtn.length())+rtn; 583 return rtn; 584 } 585 586 587 /** 588 * adds zeros add the begin of a int example: addZeros(2,3) return "002" 589 * @param i number to add nulls 590 * @param size 591 * @return min len of return value; 592 */ 593 public static String addZeros(long i, int size) { 594 String rtn=Caster.toString(i); 595 if(rtn.length()<size) return repeatString("0",size-rtn.length())+rtn; 596 return rtn; 597 } 598 599 public static int indexOf(String haystack, String needle) { 600 if(haystack==null) return -1; 601 return haystack.indexOf(needle); 602 } 603 604 public static int indexOfIgnoreCase(String haystack, String needle) { 605 if(StringUtil.isEmpty(haystack) || StringUtil.isEmpty(needle)) return -1; 606 needle=needle.toLowerCase(); 607 608 int lenHaystack=haystack.length(); 609 int lenNeedle=needle.length(); 610 611 char lastNeedle=needle.charAt(lenNeedle-1); 612 char c; 613 outer:for(int i=lenNeedle-1;i<lenHaystack;i++) { 614 c=Character.toLowerCase(haystack.charAt(i)); 615 if(c==lastNeedle) { 616 for(int y=0;y<lenNeedle-1;y++) { 617 if(needle.charAt(y)!=Character.toLowerCase(haystack.charAt(i-(lenNeedle-1)+y))) 618 continue outer; 619 } 620 return i-(lenNeedle-1); 621 } 622 } 623 624 625 return -1; 626 } 627 628 /** 629 * Tests if this string starts with the specified prefix. 630 * @param str string to check first char 631 * @param prefix the prefix. 632 * @return is first of given type 633 */ 634 public static boolean startsWith(String str, char prefix) { 635 return str!=null && str.length()>0 && str.charAt(0)==prefix; 636 } 637 638 /** 639 * Tests if this string ends with the specified suffix. 640 * @param str string to check first char 641 * @param suffix the suffix. 642 * @return is last of given type 643 */ 644 public static boolean endsWith(String str, char suffix) { 645 return str!=null && str.length()>0 && str.charAt(str.length()-1)==suffix; 646 } 647 648 /** 649 * Tests if this string ends with the specified suffix. 650 * @param str string to check first char 651 * @param suffix the suffix. 652 * @return is last of given type 653 */ 654 /** 655 * Helper functions to query a strings start portion. The comparison is case insensitive. 656 * 657 * @param base the base string. 658 * @param start the starting text. 659 * 660 * @return true, if the string starts with the given starting text. 661 */ 662 public static boolean startsWithIgnoreCase(final String base, final String start) { 663 if (base.length() < start.length()) { 664 return false; 665 } 666 return base.regionMatches(true, 0, start, 0, start.length()); 667 } 668 669 /** 670 * Helper functions to query a strings end portion. The comparison is case insensitive. 671 * 672 * @param base the base string. 673 * @param end the ending text. 674 * 675 * @return true, if the string ends with the given ending text. 676 */ 677 public static boolean endsWithIgnoreCase(final String base, final String end) { 678 if (base.length() < end.length()) { 679 return false; 680 } 681 return base.regionMatches(true, base.length() - end.length(), end, 0, end.length()); 682 } 683 684 685 686 /** 687 * returns if byte arr is a BOM character Stream (UTF-8,UTF-16) 688 * @param barr 689 * @return is BOM or not 690 */ 691 public static boolean isBOM(byte[] barr) { 692 return barr.length>=3 && barr[0]==0xEF && barr[1]==0xBB && barr[2]==0xBF; 693 } 694 695 /** 696 * return "" if value is null otherwise return same string 697 * @param str 698 * @return string (not null) 699 */ 700 public static String valueOf(String str) { 701 if(str==null)return ""; 702 return str; 703 } 704 705 706 /** 707 * cast a string a lower case String, is faster than the String.toLowerCase, if all Character are already Low Case 708 * @param str 709 * @return lower case value 710 */ 711 public static String toLowerCase(String str) { 712 int len=str.length(); 713 char c; 714 for(int i=0;i<len;i++) { 715 c=str.charAt(i); 716 if(!((c>='a' && c<='z') || (c>='0' && c<='9'))) { 717 return str.toLowerCase(); 718 } 719 } 720 721 return str; 722 } 723 public static String toUpperCase(String str) { 724 int len=str.length(); 725 char c; 726 for(int i=0;i<len;i++) { 727 c=str.charAt(i); 728 if(!((c>='A' && c<='Z') || (c>='0' && c<='9'))) { 729 return str.toUpperCase(); 730 } 731 } 732 733 return str; 734 } 735 736 /** 737 * soundex function 738 * @param str 739 * @return soundex from given string 740 */ 741 public static String soundex(String str) { 742 return new org.apache.commons.codec.language.Soundex().soundex(str); 743 } 744 745 /** 746 * return the last character of a string, if string ist empty return 0; 747 * @param str string to get last character 748 * @return last character 749 */ 750 public static char lastChar(String str) { 751 if(str==null || str.length()==0) return 0; 752 return str.charAt(str.length()-1); 753 } 754 755 756 /** 757 * 758 * @param str 759 * @return return if a String is "Empty", that means NULL or String with length 0 (whitespaces will not counted) 760 */ 761 public static boolean isEmpty(String str) { 762 return str==null || str.length()==0; 763 } 764 /** 765 * 766 * @param str 767 * @return return if a String is "Empty", that means NULL or String with length 0 (whitespaces will not counted) 768 */ 769 public static boolean isEmpty(String str, boolean trim) { 770 if(!trim) return isEmpty(str); 771 return str==null || str.trim().length()==0; 772 } 773 774 /** 775 * return the first character of a string, if string ist empty return 0; 776 * @param str string to get first character 777 * @return first character 778 */ 779 public static char firstChar(String str) { 780 if(isEmpty(str)) return 0; 781 return str.charAt(0); 782 } 783 784 /** 785 * change charset of string from system default to givenstr 786 * @param str 787 * @param charset 788 * @return 789 * @throws UnsupportedEncodingException 790 */ 791 public static String changeCharset(String str, String charset) throws UnsupportedEncodingException { 792 if(str==null) return str; 793 return new String(str.getBytes(charset),charset); 794 } 795 796 /** 797 * change charset of string from system default to givenstr 798 * @param str 799 * @param charset 800 * @return 801 * @throws UnsupportedEncodingException 802 */ 803 public static String changeCharset(String str, String charset, String defaultValue) { 804 if(str==null) return str; 805 try { 806 return new String(str.getBytes(SystemUtil.getCharset()),charset); 807 } catch (UnsupportedEncodingException e) { 808 return defaultValue; 809 } 810 } 811 812 public static boolean isWhiteSpace(char c) { 813 return c<=' '; 814 } 815 816 public static String removeWhiteSpace(String str) { 817 if(isEmpty(str)) return str; 818 StringBuilder sb=new StringBuilder(); 819 char[] carr = str.trim().toCharArray(); 820 for(int i=0;i<carr.length;i++) { 821 if(!isWhiteSpace(carr[i]))sb.append(carr[i]); 822 } 823 return sb.toString(); 824 } 825 826 public static String replaceLast(String str, char from, char to) { 827 int index = str.lastIndexOf(from); 828 if(index==-1)return str; 829 return str.substring(0,index)+to+str.substring(index+1); 830 } 831 public static String replaceLast(String str, String from, String to) { 832 int index = str.lastIndexOf(from); 833 if(index==-1)return str; 834 return str.substring(0,index)+to+str.substring(index+from.length()); 835 } 836 837 /** 838 * removes quotes(",') that wraps the string 839 * @param string 840 * @return 841 */ 842 public static String removeQuotes(String string,boolean trim) { 843 if(trim)string=string.trim(); 844 if((StringUtil.startsWith(string, '"') && StringUtil.endsWith(string, '"')) || (StringUtil.startsWith(string, '\'') && StringUtil.endsWith(string, '\''))){ 845 string= string.substring(1,string.length()-1); 846 if(trim)string=string.trim(); 847 } 848 return string; 849 } 850 851 public static boolean isEmpty(Object obj, boolean trim) { 852 if(obj==null) return true; 853 if(obj instanceof String)return isEmpty((String)obj,trim); 854 if(obj instanceof StringBuffer)return isEmpty((StringBuffer)obj,trim); 855 if(obj instanceof StringBuilder)return isEmpty((StringBuilder)obj,trim); 856 if(obj instanceof Collection.Key)return isEmpty(((Collection.Key)obj).getString(),trim); 857 return false; 858 } 859 860 public static boolean isEmpty(Object obj) { 861 if(obj==null) return true; 862 if(obj instanceof String)return isEmpty((String)obj); 863 if(obj instanceof Collection.Key)return isEmpty(((Collection.Key)obj).getString()); 864 if(obj instanceof StringBuffer)return isEmpty((StringBuffer)obj); 865 if(obj instanceof StringBuilder)return isEmpty((StringBuilder)obj); 866 return false; 867 } 868 869 public static boolean isEmpty(StringBuffer sb,boolean trim) { 870 if(trim) return sb==null || sb.toString().trim().length()==0; 871 return sb==null || sb.length()==0; 872 } 873 public static boolean isEmpty(StringBuilder sb,boolean trim) { 874 if(trim) return sb==null || sb.toString().trim().length()==0; 875 return sb==null || sb.length()==0; 876 } 877 878 public static boolean isEmpty(StringBuffer sb) { 879 return sb==null || sb.length()==0; 880 } 881 882 public static boolean isEmpty(StringBuilder sb) { 883 return sb==null || sb.length()==0; 884 } 885 886 public static String removeStarting(String str, String sub) { 887 if(isEmpty(str) || isEmpty(sub) || !str.startsWith(sub)) return str; 888 return str.substring(sub.length()); 889 } 890 891 public static String removeStartingIgnoreCase(String str, String sub) { 892 if(isEmpty(sub) || !startsWithIgnoreCase(str, sub)) return str; 893 return str.substring(sub.length()); 894 } 895 896 897 public static String[] merge(String str, String[] arr) { 898 String[] narr=new String[arr.length+1]; 899 narr[0]=str; 900 for(int i=0;i<arr.length;i++) { 901 narr[i+1]=arr[i]; 902 } 903 return narr; 904 905 } 906 907 public static int length(String str) { 908 if(str==null) return 0; 909 return str.length(); 910 } 911 912 public static boolean hasUpperCase(String str) { 913 if(isEmpty(str)) return false; 914 return !str.equals(str.toLowerCase()); 915 } 916 917 /** 918 * trim given value, return defaultvalue when input is null 919 * @param str 920 * @param defaultValue 921 * @return trimmed string or defaultValue 922 */ 923 public static String trim(String str,String defaultValue) { 924 if(str==null) return defaultValue; 925 return str.trim(); 926 } 927 928 public static boolean contains(String str, String substr) { 929 if(str==null) return false; 930 return str.indexOf(substr)!=-1; 931 } 932 933 public static boolean containsIgnoreCase(String str, String substr) { 934 return indexOfIgnoreCase(str,substr)!=-1; 935 } 936 937 public static String substringEL(String str, int index,String defaultValue) { 938 if(str==null || index<0 || index>str.length()) return defaultValue; 939 return str.substring(index); 940 } 941 942 /** 943 * translate a string in camel notation to a string in hypen notation 944 * example: 945 * helloWorld -> hello-world 946 * @param str 947 * @return 948 */ 949 public static String camelToHypenNotation(String str) { 950 if(isEmpty(str)) return str; 951 952 StringBuilder sb=new StringBuilder(); 953 //int len=str.length(); 954 char c; 955 956 sb.append(Character.toLowerCase(str.charAt(0))); 957 for(int i=1;i<str.length();i++){ 958 c=str.charAt(i); 959 if(Character.isUpperCase(c)){ 960 sb.append('-'); 961 sb.append(Character.toLowerCase(c)); 962 } 963 else sb.append(c); 964 } 965 return sb.toString(); 966 } 967 968 /** 969 * translate a string in hypen notation to a string in camel notation 970 * example: 971 * hello-world -> helloWorld 972 * @param str 973 * @return 974 */ 975 public static String hypenToCamelNotation(String str) { 976 if(isEmpty(str)) return str; 977 978 StringBuilder sb=new StringBuilder(); 979 int len=str.length(); 980 char c; 981 982 for(int i=0;i<str.length();i++){ 983 c=str.charAt(i); 984 if(c=='-'){ 985 if(len>++i) sb.append(Character.toUpperCase(str.charAt(i))); 986 } 987 else sb.append(c); 988 } 989 return sb.toString(); 990 } 991 992 public static boolean isAscii(String str) { 993 994 for(int i=str.length()-1;i>=0;i--){ 995 996 if( str.charAt(i) > 127 ) 997 return false; 998 } 999 return true; 1000 } 1001 1002 public static boolean isWhiteSpace(String str) { 1003 if(str==null) return false; 1004 int len=str.length(); 1005 char c; 1006 for(int i=0;i<len;i++){ 1007 c=str.charAt(i); 1008 if(c!=' ' && c!='\t' && c!='\b' && c!='\r' && c!='\n') return false; 1009 } 1010 return true; 1011 } 1012 1013 /** 1014 * this method works different from the regular substring method, the regular substring method takes startIndex and endIndex as second and third argument, 1015 * this method takes offset and length 1016 * @param str 1017 * @param off 1018 * @param len 1019 * @return 1020 */ 1021 public static String substring(String str, int off, int len) { 1022 return str.substring(off,off+len); 1023 } 1024 1025 1026 1027 /** 1028 * this is the public entry point for the replaceMap() method 1029 * 1030 * @param input - the string on which the replacements should be performed. 1031 * @param map - a java.util.Map with key/value pairs where the key is the substring to find and the value is the substring with which to replace the matched key 1032 * @param ignoreCase - if true then matches will not be case sensitive 1033 * @return 1034 * @throws PageException 1035 */ 1036 public static String replaceMap( String input, Map map, boolean ignoreCase ) throws PageException { 1037 1038 return replaceMap( input, map, ignoreCase, true ); 1039 } 1040 1041 1042 /** 1043 * this is the core of the replaceMap() method. 1044 * 1045 * it is called once from the public entry point and then internally from resolveInternals() 1046 * 1047 * when doResolveInternals is true -- this method calls resolveInternals. therefore, calls from resolveInternals() 1048 * must pass false to that param to avoid an infinite ping-pong loop 1049 * 1050 * @param input - the string on which the replacements should be performed. 1051 * @param map - a java.util.Map with key/value pairs where the key is the substring to find and the value is the substring with which to replace the matched key 1052 * @param ignoreCase - if true then matches will not be case sensitive 1053 * @param doResolveInternals - only the initial call (from the public entry point) should pass true 1054 * @return 1055 * @throws PageException 1056 */ 1057 private static String replaceMap( String input, Map map, boolean ignoreCase, boolean doResolveInternals ) throws PageException { 1058 if ( doResolveInternals ) 1059 map = resolveInternals( map, ignoreCase, 0 ); 1060 1061 String result = input; 1062 Iterator<Map.Entry> it = map.entrySet().iterator(); 1063 Map.Entry e; 1064 while ( it.hasNext() ) { 1065 e = it.next(); 1066 result = replace( result, Caster.toString(e.getKey()), Caster.toString(e.getValue()), false, ignoreCase ); 1067 } 1068 return result; 1069 } 1070 1071 1072 1073 /** 1074 * resolves internal values within the map, so if the map has a key "{signature}" 1075 * and its value is "Team {group}" and there's a key with the value {group} whose 1076 * value is "Railo", then {signature} will resolve to "Team Railo". 1077 * 1078 * {signature} = "Team {group}" 1079 * {group} = "Railo" 1080 * 1081 * then signature will resolve to 1082 * 1083 * {signature} = "Team Railo" 1084 * 1085 * @param map - key/value pairs for find key/replace with value 1086 * @param ignoreCase - if true then matches will not be case sensitive 1087 * @param count - used internally as safety valve to ensure that we don't go into infinite loop if two values reference each-other 1088 * @return 1089 * @throws PageException 1090 */ 1091 private static Map resolveInternals( Map map, boolean ignoreCase, int count ) throws PageException { 1092 Map result = new HashMap(); 1093 Iterator<Map.Entry> it = map.entrySet().iterator(); 1094 boolean isModified = false; 1095 Map.Entry e; 1096 String v,r; 1097 while ( it.hasNext() ) { 1098 e = it.next(); 1099 v = Caster.toString( e.getValue() ); 1100 r = replaceMap( v, map, ignoreCase, false ); // pass false for last arg so that replaceMap() will not call this method in an infinite loop 1101 result.put( Caster.toString( e.getKey() ), r ); 1102 if ( !v.equalsIgnoreCase( r ) ) 1103 isModified = true; 1104 } 1105 1106 if ( isModified && count++ < map.size() ) 1107 result = resolveInternals( result, ignoreCase, count ); // recursive call 1108 1109 return result; 1110 } 1111 }