001 package railo.runtime.op; 002 003 import java.io.ByteArrayOutputStream; 004 import java.io.InputStream; 005 import java.sql.Blob; 006 import java.sql.Clob; 007 import java.text.DateFormat; 008 import java.text.ParseException; 009 import java.util.Calendar; 010 import java.util.Date; 011 import java.util.Iterator; 012 import java.util.List; 013 import java.util.Locale; 014 import java.util.Map; 015 import java.util.TimeZone; 016 import java.util.regex.Pattern; 017 018 import org.w3c.dom.Document; 019 import org.w3c.dom.Element; 020 import org.w3c.dom.Node; 021 import org.w3c.dom.NodeList; 022 023 import railo.commons.date.DateTimeUtil; 024 import railo.commons.date.JREDateTimeUtil; 025 import railo.commons.i18n.FormatUtil; 026 import railo.commons.lang.CFTypes; 027 import railo.commons.lang.StringUtil; 028 import railo.runtime.Component; 029 import railo.runtime.coder.Base64Util; 030 import railo.runtime.converter.WDDXConverter; 031 import railo.runtime.engine.ThreadLocalPageContext; 032 import railo.runtime.exp.ExpressionException; 033 import railo.runtime.exp.PageException; 034 import railo.runtime.ext.function.Function; 035 import railo.runtime.java.JavaObject; 036 import railo.runtime.net.mail.MailUtil; 037 import railo.runtime.op.date.DateCaster; 038 import railo.runtime.op.validators.ValidateCreditCard; 039 import railo.runtime.text.xml.XMLCaster; 040 import railo.runtime.text.xml.XMLUtil; 041 import railo.runtime.text.xml.struct.XMLStruct; 042 import railo.runtime.type.Array; 043 import railo.runtime.type.Closure; 044 import railo.runtime.type.Collection; 045 import railo.runtime.type.Collection.Key; 046 import railo.runtime.type.ObjectWrap; 047 import railo.runtime.type.Objects; 048 import railo.runtime.type.Query; 049 import railo.runtime.type.QueryColumn; 050 import railo.runtime.type.Struct; 051 import railo.runtime.type.UDF; 052 import railo.runtime.type.dt.DateTime; 053 054 055 /** 056 * Object to test if a Object is a specific type 057 */ 058 public final class Decision { 059 060 private static final String STRING_DEFAULT_VALUE = "this is a unique string"; 061 062 private static Pattern emailPattern; 063 private static Pattern ssnPattern; 064 private static Pattern phonePattern; 065 private static Pattern urlPattern; 066 private static Pattern zipPattern; 067 068 /** 069 * tests if value is a simple value (Number,String,Boolean,Date,Printable) 070 * @param value value to test 071 * @return is value a simple value 072 */ 073 public static boolean isSimpleValue(Object value){ 074 return 075 (value instanceof Number) || 076 (value instanceof String) || 077 (value instanceof Boolean) || 078 (value instanceof Date) || 079 ((value instanceof Castable) && !(value instanceof Objects) && !(value instanceof Collection)); 080 } 081 082 /** 083 * tests if value is Numeric 084 * @param value value to test 085 * @return is value numeric 086 */ 087 public static boolean isNumeric(Object value) { 088 if(value instanceof Number) return true; 089 else if(value instanceof String) { 090 return isNumeric(value.toString()); 091 } 092 093 else return false; 094 } 095 096 public static boolean isCastableToNumeric(Object o) { 097 098 if(isNumeric(o)) return true; 099 else if(isBoolean(o)) return true; 100 else if(isDateSimple(o,false)) return true; 101 else if(o == null) return true; 102 else if(o instanceof ObjectWrap) return isCastableToNumeric(((ObjectWrap)o).getEmbededObject("notanumber")); 103 104 else if(o instanceof Castable) { 105 return Decision.isValid(((Castable)o).castToDoubleValue(Double.NaN)); 106 107 } 108 return false; 109 } 110 111 public static boolean isCastableToDate(Object o) { 112 if(isDateAdvanced(o, true)) return true; 113 else if(isBoolean(o)) return true; 114 115 else if(o instanceof ObjectWrap) return isCastableToDate(((ObjectWrap)o).getEmbededObject("notadate")); 116 117 else if(o instanceof Castable) { 118 return ((Castable)o).castToDateTime(null)!=null; 119 120 } 121 return false; 122 } 123 124 /** 125 * tests if value is Numeric 126 * @param value value to test 127 * @return is value numeric 128 */ 129 public static boolean isNumeric(Object value, boolean alsoBooleans) { 130 if(alsoBooleans && isBoolean(value)) return true; 131 return isNumeric(value); 132 } 133 134 /** 135 * tests if String value is Numeric 136 * @param str value to test 137 * @return is value numeric 138 */ 139 public static boolean isNumeric(String str) { 140 if(str==null) return false; 141 str=str.trim(); 142 143 int pos=0; 144 int len=str.length(); 145 if(len==0) return false; 146 char curr=str.charAt(pos); 147 148 if(curr=='+' || curr=='-') { 149 if(len==++pos) return false; 150 curr=str.charAt(pos); 151 } 152 153 boolean hasDot=false; 154 boolean hasExp=false; 155 for(;pos<len;pos++) { 156 curr=str.charAt(pos); 157 if(curr<'0') { 158 if(curr=='.') { 159 if(pos+1>=len || hasDot) return false; 160 hasDot=true; 161 } 162 else return false; 163 } 164 else if(curr>'9') { 165 if(curr=='e' || curr=='E') { 166 if(pos+1>=len || hasExp) return false; 167 hasExp=true; 168 hasDot=true; 169 } 170 else return false; 171 } 172 } 173 if(hasExp){ 174 try{ 175 Double.parseDouble(str); 176 return true; 177 } 178 catch( NumberFormatException e){ 179 return false; 180 } 181 } 182 return true; 183 } 184 185 186 public static boolean isInteger(Object value) { 187 return isInteger(value,false); 188 } 189 190 public static boolean isInteger(Object value,boolean alsoBooleans) { 191 if(!alsoBooleans && value instanceof Boolean) return false; 192 double dbl = Caster.toDoubleValue(value,Double.NaN); 193 if(!Decision.isValid(dbl)) return false; 194 int i=(int)dbl; 195 return i==dbl; 196 } 197 198 /** tests if String value is Hex Value 199 * @param str value to test 200 * @return is value numeric 201 */ 202 public static boolean isHex(String str) { 203 if(str==null || str.length()==0) return false; 204 205 for(int i=str.length()-1;i>=0;i--) { 206 char c=str.charAt(i); 207 if(!(c>='0' && c<='9')) { 208 c=Character.toLowerCase(c); 209 if(!(c=='a' || c=='b' || c=='c' || c=='d' || c=='e' || c=='f'))return false; 210 } 211 } 212 return true; 213 } 214 215 /** tests if String value is UUID Value 216 * @param obj value to test 217 * @return is value numeric 218 * @deprecated use instead <code>isUUId(Object obj)</code> 219 */ 220 public static boolean isUUID(Object obj) { 221 return isUUId(obj); 222 } 223 224 /** tests if String value is UUID Value 225 * @param obj value to test 226 * @return is value numeric 227 */ 228 public static boolean isUUId(Object obj) { 229 String str=Caster.toString(obj,null); 230 if(str==null) return false; 231 232 if(str.length()==35) { 233 return 234 Decision.isHex(str.substring(0,8)) && 235 str.charAt(8)=='-' && 236 Decision.isHex(str.substring(9,13)) && 237 str.charAt(13)=='-' && 238 Decision.isHex(str.substring(14,18)) && 239 str.charAt(18)=='-' && 240 Decision.isHex(str.substring(19)); 241 } 242 else if(str.length()==32) 243 return Decision.isHex(str); 244 return false; 245 } 246 247 248 /** 249 * @param obj 250 * @return 251 * @deprecated use instead <code>isGUId(Object)</code> 252 */ 253 public static boolean isGUID(Object obj) { 254 return isGUId(obj); 255 } 256 257 public static boolean isGUId(Object obj) { 258 String str=Caster.toString(obj,null); 259 if(str==null) return false; 260 261 262 // GUID 263 if(str.length()==36) { 264 return 265 Decision.isHex(str.substring(0,8)) && 266 str.charAt(8)=='-' && 267 Decision.isHex(str.substring(9,13)) && 268 str.charAt(13)=='-' && 269 Decision.isHex(str.substring(14,18)) && 270 str.charAt(18)=='-' && 271 Decision.isHex(str.substring(19,23)) && 272 str.charAt(23)=='-' && 273 Decision.isHex(str.substring(24)); 274 } 275 return false; 276 } 277 278 279 public static boolean isGUIdSimple(Object obj) { 280 String str=Caster.toString(obj,null); 281 if(str==null) return false; 282 283 284 // GUID 285 if(str.length()==36) { 286 return 287 str.charAt(8)=='-' && 288 str.charAt(13)=='-' && 289 str.charAt(18)=='-' && 290 str.charAt(23)=='-'; 291 } 292 return false; 293 } 294 295 /** 296 * tests if value is a Boolean (Numbers are not acctepeted) 297 * @param value value to test 298 * @return is value boolean 299 */ 300 public static boolean isBoolean(Object value) { 301 if(value instanceof Boolean) return true; 302 else if(value instanceof String) { 303 return isBoolean(value.toString()); 304 } 305 else if(value instanceof ObjectWrap) return isBoolean(((ObjectWrap)value).getEmbededObject(null)); 306 else return false; 307 } 308 309 public static boolean isCastableToBoolean(Object value) { 310 if(value instanceof Boolean) return true; 311 if(value instanceof Number) return true; 312 else if(value instanceof String) { 313 String str = (String)value; 314 return isBoolean(str) || isNumeric(str); 315 } 316 else if(value instanceof Castable) { 317 return ((Castable)value).castToBoolean(null)!=null; 318 319 } 320 else if(value instanceof ObjectWrap) return isCastableToBoolean(((ObjectWrap)value).getEmbededObject(null)); 321 else return false; 322 } 323 324 public static boolean isBoolean(Object value, boolean alsoNumbers) { 325 if(isBoolean(value)) return true; 326 else if(alsoNumbers) return isNumeric(value); 327 else return false; 328 } 329 330 /** 331 * tests if value is a Boolean 332 * @param str value to test 333 * @return is value boolean 334 */ 335 public static boolean isBoolean(String str) { 336 //str=str.trim(); 337 if(str.length()<2) return false; 338 339 switch(str.charAt(0)) { 340 case 't': 341 case 'T': return str.equalsIgnoreCase("true"); 342 case 'f': 343 case 'F': return str.equalsIgnoreCase("false"); 344 case 'y': 345 case 'Y': return str.equalsIgnoreCase("yes"); 346 case 'n': 347 case 'N': return str.equalsIgnoreCase("no"); 348 } 349 return false; 350 } 351 352 /** 353 * tests if value is DateTime Object 354 * @param value value to test 355 * @param alsoNumbers interpret also a number as date 356 * @return is value a DateTime Object 357 */ 358 public static boolean isDate(Object value,boolean alsoNumbers) { 359 return isDateSimple(value, alsoNumbers); 360 } 361 362 public static boolean isDateSimple(Object value,boolean alsoNumbers) { 363 return isDateSimple(value, alsoNumbers, false); 364 } 365 public static boolean isDateSimple(Object value,boolean alsoNumbers, boolean alsoMonthString) { 366 367 //return DateCaster.toDateEL(value)!=null; 368 if(value instanceof DateTime) return true; 369 else if(value instanceof Date) return true; 370 // wrong timezone but this isent importend because date will not be importend 371 else if(value instanceof String) return DateCaster.toDateSimple(value.toString(),alsoNumbers,alsoMonthString,TimeZone.getDefault(),null)!=null; 372 else if(value instanceof ObjectWrap) { 373 return isDateSimple(((ObjectWrap)value).getEmbededObject(null),alsoNumbers); 374 } 375 else if(value instanceof Castable) { 376 return ((Castable)value).castToDateTime(null)!=null; 377 378 } 379 else if(alsoNumbers && value instanceof Number) return true; 380 else if(value instanceof Calendar) return true; 381 return false; 382 } 383 384 public static boolean isDateAdvanced(Object value,boolean alsoNumbers) { 385 //return DateCaster.toDateEL(value)!=null; 386 if(value instanceof DateTime) return true; 387 else if(value instanceof Date) return true; 388 // wrong timezone but this isent importend because date will not be importend 389 else if(value instanceof String) return DateCaster.toDateAdvanced(value.toString(),alsoNumbers,TimeZone.getDefault(),null)!=null; 390 else if(value instanceof Castable) { 391 return ((Castable)value).castToDateTime(null)!=null; 392 393 } 394 else if(alsoNumbers && value instanceof Number) return true; 395 else if(value instanceof ObjectWrap) { 396 return isDateAdvanced(((ObjectWrap)value).getEmbededObject(null),alsoNumbers); 397 } 398 else if(value instanceof Calendar) return true; 399 return false; 400 } 401 402 private static char[] DATE_DEL=new char[]{'.','/','-'}; 403 404 public static boolean isUSDate(Object value) { 405 String str = Caster.toString(value,""); 406 return isUSorEuroDateEuro(str,false); 407 } 408 409 public static boolean isUSDate(String str) { 410 return isUSorEuroDateEuro(str,false); 411 } 412 413 public static boolean isEuroDate(Object value) { 414 String str = Caster.toString(value,""); 415 return isUSorEuroDateEuro(str,true); 416 } 417 418 public static boolean isEuroDate(String str) { 419 return isUSorEuroDateEuro(str,true); 420 } 421 422 private static boolean isUSorEuroDateEuro(String str, boolean isEuro) { 423 if(StringUtil.isEmpty(str)) return false; 424 425 for(int i=0;i<DATE_DEL.length;i++) { 426 Array arr = railo.runtime.type.util.ListUtil.listToArrayRemoveEmpty(str,DATE_DEL[i]); 427 if(arr.size()!=3) continue; 428 429 int month=Caster.toIntValue( arr.get(isEuro?2:1,Constants.INTEGER_0),Integer.MIN_VALUE); 430 int day=Caster.toIntValue( arr.get(isEuro?1:2,Constants.INTEGER_0),Integer.MIN_VALUE); 431 int year=Caster.toIntValue( arr.get(3,Constants.INTEGER_0),Integer.MIN_VALUE); 432 433 434 if(month==Integer.MIN_VALUE) continue; 435 if(month>12) continue; 436 if(day==Integer.MIN_VALUE) continue; 437 if(day>31) continue; 438 if(year==Integer.MIN_VALUE) continue; 439 if(DateTimeUtil.getInstance().toTime(null,year, month, day, 0, 0, 0,0, Long.MIN_VALUE)==Long.MIN_VALUE) continue; 440 return true; 441 } 442 return false; 443 } 444 445 public static boolean isCastableToStruct(Object o) { 446 if(isStruct(o)) return true; 447 if(o == null) return false; 448 else if(o instanceof ObjectWrap) { 449 if(o instanceof JavaObject ) return true; 450 return isCastableToStruct(((ObjectWrap)o).getEmbededObject(null)); 451 } 452 if(Decision.isSimpleValue(o)){ 453 return false; 454 } 455 //if(isArray(o) || isQuery(o)) return false; 456 return false; 457 } 458 459 /** 460 * tests if object is a struct 461 * @param o 462 * @return is struct or not 463 */ 464 public static boolean isStruct(Object o) { 465 if(o instanceof Struct) return true; 466 else if(o instanceof Map)return true; 467 else if(o instanceof Node)return true; 468 return false; 469 } 470 471 472 /** 473 * can this type be casted to a array 474 * @param o 475 * @return 476 * @throws PageException 477 */ 478 public static boolean isCastableToArray(Object o) { 479 if(isArray(o)) return true; 480 //else if(o instanceof XMLStruct) return true; 481 else if(o instanceof Struct) { 482 Struct sct=(Struct) o; 483 Iterator<Key> it = sct.keyIterator(); 484 try { 485 while(it.hasNext()) { 486 Caster.toIntValue(it.next().getString()); 487 } 488 return true; 489 } 490 catch (Throwable t) { 491 return false; 492 } 493 } 494 return false; 495 } 496 497 /** 498 * tests if object is a array 499 * @param o 500 * @return is array or not 501 */ 502 public static boolean isArray(Object o) { 503 if(o instanceof Array) return true; 504 if(o instanceof List) return true; 505 if(isNativeArray(o)) return true; 506 if(o instanceof ObjectWrap) { 507 return isArray(((ObjectWrap)o).getEmbededObject(null)); 508 } 509 return false; 510 } 511 512 /** 513 * tests if object is a native java array 514 * @param o 515 * @return is a native (java) array 516 */ 517 public static boolean isNativeArray(Object o) { 518 //return o.getClass().isArray(); 519 if(o instanceof Object[]) return true; 520 else if(o instanceof boolean[]) return true; 521 else if(o instanceof byte[]) return true; 522 else if(o instanceof char[]) return true; 523 else if(o instanceof short[]) return true; 524 else if(o instanceof int[]) return true; 525 else if(o instanceof long[]) return true; 526 else if(o instanceof float[]) return true; 527 else if(o instanceof double[]) return true; 528 return false; 529 } 530 531 /** 532 * tests if object is catable to a binary 533 * @param object 534 * @return boolean 535 */ 536 public static boolean isCastableToBinary(Object object,boolean checkBase64String) { 537 if(isBinary(object))return true; 538 if(object instanceof InputStream) return true; 539 if(object instanceof ByteArrayOutputStream) return true; 540 if(object instanceof Blob) return true; 541 542 // Base64 String 543 if(!checkBase64String) return false; 544 String str = Caster.toString(object,null); 545 if(str==null) return false; 546 return Base64Util.isBase64(str); 547 548 } 549 550 /** 551 * tests if object is a binary 552 * @param object 553 * @return boolean 554 */ 555 public static boolean isBinary(Object object) { 556 if(object instanceof byte[]) return true; 557 if(object instanceof ObjectWrap) return isBinary(((ObjectWrap)object).getEmbededObject("")); 558 return false; 559 } 560 561 /** 562 * tests if object is a Component 563 * @param object 564 * @return boolean 565 */ 566 public static boolean isComponent(Object object) { 567 return object instanceof Component; 568 } 569 570 /** 571 * tests if object is a Query 572 * @param object 573 * @return boolean 574 */ 575 public static boolean isQuery(Object object) { 576 if(object instanceof Query)return true; 577 else if(object instanceof ObjectWrap) { 578 return isQuery(((ObjectWrap)object).getEmbededObject(null)); 579 } 580 return false; 581 } 582 public static boolean isQueryColumn(Object object) { 583 if(object instanceof QueryColumn)return true; 584 else if(object instanceof ObjectWrap) { 585 return isQueryColumn(((ObjectWrap)object).getEmbededObject(null)); 586 } 587 return false; 588 } 589 590 /** 591 * tests if object is a binary 592 * @param object 593 * @return boolean 594 */ 595 public static boolean isUserDefinedFunction(Object object) { 596 return object instanceof UDF; 597 } 598 599 /** 600 * tests if year is a leap year 601 * @param year year to check 602 * @return boolean 603 */ 604 public static final boolean isLeapYear(int year) { 605 return DateTimeUtil.getInstance().isLeapYear(year); 606 //return new GregorianCalendar().isLeapYear(year); 607 } 608 609 /** 610 * tests if object is a WDDX Object 611 * @param o Object to check 612 * @return boolean 613 */ 614 public static boolean isWddx(Object o) { 615 if(!(o instanceof String)) return false; 616 String str=o.toString(); 617 if(!(str.indexOf("wddxPacket")>0)) return false; 618 619 // wrong timezone but this isent importend because date will not be used 620 WDDXConverter converter =new WDDXConverter(TimeZone.getDefault(),false,true); 621 try { 622 converter.deserialize(Caster.toString(o),true); 623 } 624 catch (Exception e) { 625 return false; 626 } 627 return true; 628 } 629 630 /** 631 * tests if object is a XML Object 632 * @param o Object to check 633 * @return boolean 634 */ 635 public static boolean isXML(Object o) { 636 if(o instanceof Node || o instanceof NodeList) return true; 637 if(o instanceof ObjectWrap) { 638 return isXML(((ObjectWrap)o).getEmbededObject(null)); 639 } 640 try { 641 XMLCaster.toXMLStruct(XMLUtil.parse(XMLUtil.toInputSource(null, o),null,false),false); 642 return true; 643 } 644 catch(Exception outer) { 645 return false; 646 } 647 648 } 649 650 public static boolean isVoid(Object o) { 651 if(o==null)return true; 652 else if(o instanceof String) return o.toString().length()==0; 653 else if(o instanceof Number) return ((Number)o).intValue()==0; 654 else if(o instanceof Boolean) return ((Boolean)o).booleanValue()==false ; 655 else if(o instanceof ObjectWrap)return isVoid(((ObjectWrap)o).getEmbededObject(("isnotnull"))); 656 return false; 657 } 658 659 660 /** 661 * tests if object is a XML Element Object 662 * @param o Object to check 663 * @return boolean 664 */ 665 public static boolean isXMLElement(Object o) { 666 return o instanceof Element; 667 } 668 669 /** 670 * tests if object is a XML Document Object 671 * @param o Object to check 672 * @return boolean 673 */ 674 public static boolean isXMLDocument(Object o) { 675 return o instanceof Document; 676 } 677 678 /** 679 * tests if object is a XML Root Element Object 680 * @param o Object to check 681 * @return boolean 682 */ 683 public static boolean isXMLRootElement(Object o) { 684 if(o instanceof Node) { 685 Node n=(Node)o; 686 if(n instanceof XMLStruct)n=((XMLStruct)n).toNode(); 687 return n.getOwnerDocument()!=null && n.getOwnerDocument().getDocumentElement()==n; 688 } 689 return false; 690 } 691 692 /** 693 * @param obj 694 * @return returns if string represent a variable name 695 */ 696 public static boolean isVariableName(Object obj) { 697 if(obj instanceof String) return isVariableName((String)obj); 698 return false; 699 } 700 701 public static boolean isFunction(Object obj) { 702 if(obj instanceof UDF)return true; 703 else if(obj instanceof ObjectWrap) { 704 return isFunction(((ObjectWrap)obj).getEmbededObject(null)); 705 } 706 return false; 707 } 708 709 public static boolean isClosure(Object obj) { 710 if(obj instanceof Closure)return true; 711 else if(obj instanceof ObjectWrap) { 712 return isClosure(((ObjectWrap)obj).getEmbededObject(null)); 713 } 714 return false; 715 } 716 717 /** 718 * @param string 719 * @return returns if string represent a variable name 720 */ 721 public static boolean isVariableName(String string) { 722 if(string.length()==0)return false; 723 int len=string.length(); 724 int pos=0; 725 while(pos<len) { 726 char first=string.charAt(pos); 727 if(!((first>='a' && first<='z')||(first>='A' && first<='Z')||(first=='_'))) 728 return false; 729 pos++; 730 for(;pos<len;pos++) { 731 char c=string.charAt(pos); 732 if(!((c>='a' && c<='z')||(c>='A' && c<='Z')||(c>='0' && c<='9')||(c=='_'))) 733 break; 734 } 735 if(pos==len) return true; 736 if(string.charAt(pos)=='.')pos++; 737 } 738 return false; 739 } 740 741 /** 742 * @param string 743 * @return returns if string represent a variable name 744 */ 745 public static boolean isSimpleVariableName(String string) { 746 if(string.length()==0)return false; 747 748 char first=string.charAt(0); 749 if(!((first>='a' && first<='z')||(first>='A' && first<='Z')||(first=='_'))) 750 return false; 751 for(int i=string.length()-1;i>0;i--) { 752 char c=string.charAt(i); 753 if(!((c>='a' && c<='z')||(c>='A' && c<='Z')||(c>='0' && c<='9')||(c=='_'))) 754 return false; 755 } 756 return true; 757 } 758 759 /** 760 * @param key 761 * @return returns if string represent a variable name 762 */ 763 public static boolean isSimpleVariableName(Collection.Key key) { 764 String strKey = key.getLowerString(); 765 if(strKey.length()==0)return false; 766 767 char first=strKey.charAt(0); 768 if(!((first>='a' && first<='z')||(first=='_'))) 769 return false; 770 for(int i=strKey.length()-1;i>0;i--) { 771 char c=strKey.charAt(i); 772 if(!((c>='a' && c<='z')||(c>='0' && c<='9')||(c=='_'))) 773 return false; 774 } 775 return true; 776 } 777 778 /** 779 * returns if object is a CFML object 780 * @param o Object to check 781 * @return is or not 782 */ 783 public static boolean isObject(Object o) { 784 return isComponent(o) 785 786 || (!isArray(o) 787 && !isQuery(o) 788 && !isSimpleValue(o) 789 && !isStruct(o) 790 && !isUserDefinedFunction(o) 791 && !isXML(o)); 792 } 793 794 /** 795 * @param obj 796 * @return return if a String is "Empty", that means NULL or String with length 0 (whitespaces will not counted) 797 */ 798 public static boolean isEmpty(Object obj) { 799 if(obj instanceof String)return StringUtil.isEmpty((String)obj); 800 return obj==null; 801 } 802 803 804 /** 805 * @deprecated use instead <code>StringUtil.isEmpty(String)</code> 806 * @param str 807 * @return return if a String is "Empty", that means NULL or String with length 0 (whitespaces will not counted) 808 */ 809 public static boolean isEmpty(String str) { 810 return StringUtil.isEmpty(str); 811 } 812 813 /** 814 * @deprecated use instead <code>StringUtil.isEmpty(String)</code> 815 * @param str 816 * @param trim 817 * @return return if a String is "Empty", that means NULL or String with length 0 (whitespaces will not counted) 818 */ 819 public static boolean isEmpty(String str, boolean trim) { 820 return StringUtil.isEmpty(str,trim); 821 } 822 823 824 /** 825 * returns if a value is a credit card 826 * @param value 827 * @return is credit card 828 */ 829 public static boolean isCreditCard(Object value) { 830 return ValidateCreditCard.isValid(Caster.toString(value,"0")); 831 } 832 833 834 /** 835 * returns if given object is a email 836 * @param value 837 * @return 838 */ 839 public static boolean isEmail(Object value) { 840 841 return MailUtil.isValidEmail(value); 842 } 843 844 845 846 /** 847 * returns if given object is a social security number (usa) 848 * @param value 849 * @return 850 */ 851 public static boolean isSSN(Object value) { 852 String str = Caster.toString(value,null); 853 if(str==null)return false; 854 855 if(ssnPattern==null) 856 ssnPattern=Pattern.compile("^[0-9]{3}[-|]{1}[0-9]{2}[-|]{1}[0-9]{4}$"); 857 858 return ssnPattern.matcher(str.trim()).matches(); 859 860 } 861 862 /** 863 * returns if given object is a phone 864 * @param value 865 * @return 866 */ 867 public static boolean isPhone(Object value) { 868 String str = Caster.toString(value,null); 869 if(str==null)return false; 870 871 if(phonePattern==null) 872 phonePattern=Pattern.compile("^(\\+?1?[ \\-\\.]?([\\(]?([1-9][0-9]{2})[\\)]?))?[ ,\\-,\\.]?([^0-1]){1}([0-9]){2}[ ,\\-,\\.]?([0-9]){4}(( )((x){0,1}([0-9]){1,5}){0,1})?$"); 873 return phonePattern.matcher(str.trim()).matches(); 874 875 } 876 877 /** 878 * returns if given object is a URL 879 * @param value 880 * @return 881 */ 882 public static boolean isURL(Object value) { 883 String str = Caster.toString(value,null); 884 if(str==null)return false; 885 886 if(urlPattern==null) 887 urlPattern=Pattern.compile("^((http|https|ftp|file)\\:\\/\\/([a-zA-Z0-0]*:[a-zA-Z0-0]*(@))?[a-zA-Z0-9-\\.]+(\\.[a-zA-Z]{2,3})?(:[a-zA-Z0-9]*)?\\/?([a-zA-Z0-9-\\._\\? \\,\\'\\/\\+&%\\$#\\=~])*)|((mailto)\\:[a-zA-Z0-9-]+(\\.[a-zA-Z0-9-]+)*@([a-zA-Z0-9-]+\\.)+[a-zA-Z0-9]{2,7})|((news)\\: [a-zA-Z0-9\\.]*)$"); 888 return urlPattern.matcher(str.trim()).matches(); 889 } 890 891 /** 892 * returns if given object is a zip code 893 * @param value 894 * @return 895 */ 896 public static boolean isZipCode(Object value) { 897 String str = Caster.toString(value,null); 898 if(str==null)return false; 899 900 if(zipPattern==null) 901 zipPattern=Pattern.compile("([0-9]{5,5})|([0-9]{5,5}[- ]{1}[0-9]{4,4})"); 902 return zipPattern.matcher(str.trim()).matches(); 903 } 904 905 public static boolean isString(Object o) { 906 if(o instanceof String) return true; 907 else if(o instanceof Boolean) return true; 908 else if(o instanceof Number) return true; 909 else if(o instanceof Date) return true; 910 else if(o instanceof Castable) { 911 return ((Castable)o).castToString(STRING_DEFAULT_VALUE)!=STRING_DEFAULT_VALUE; 912 913 } 914 else if(o instanceof Clob) return true; 915 else if(o instanceof Node) return true; 916 else if(o instanceof Map || o instanceof List || o instanceof Function) return false; 917 else if(o == null) return true; 918 else if(o instanceof ObjectWrap) return isString(((ObjectWrap)o).getEmbededObject("")); 919 return true; 920 } 921 public static boolean isCastableToString(Object o) { 922 return isString(o); 923 } 924 925 926 public static boolean isValid(String type, Object value) throws ExpressionException { 927 type=StringUtil.toLowerCase(type.trim()); 928 char first = type.charAt(0); 929 switch(first) { 930 case 'a': 931 if("any".equals(type)) return true;//isSimpleValue(value); 932 if("array".equals(type)) return isArray(value); 933 break; 934 case 'b': 935 if("binary".equals(type)) return isBinary(value); 936 if("boolean".equals(type)) return isBoolean(value,true); 937 break; 938 case 'c': 939 if("creditcard".equals(type)) return isCreditCard(value); 940 if("component".equals(type)) return isComponent(value); 941 if("cfc".equals(type)) return isComponent(value); 942 break; 943 case 'd': 944 if("date".equals(type)) return isDateAdvanced(value,true); // ist zwar nicht logisch aber ident. zu Neo 945 if("double".equals(type)) return isCastableToNumeric(value); 946 break; 947 case 'e': 948 if("eurodate".equals(type)) return isEuroDate(value); 949 if("email".equals(type)) return isEmail(value); 950 break; 951 case 'f': 952 if("float".equals(type)) return isNumeric(value,true); 953 if("function".equals(type)) return isFunction(value); 954 break; 955 case 'g': 956 if("guid".equals(type)) return isGUId(value); 957 break; 958 case 'i': 959 if("integer".equals(type)) return isInteger(value,false); 960 break; 961 case 'n': 962 if("numeric".equals(type)) return isCastableToNumeric(value); 963 if("number".equals(type)) return isCastableToNumeric(value); 964 if("node".equals(type)) return isXML(value); 965 break; 966 case 'p': 967 if("phone".equals(type)) return isPhone(value); 968 break; 969 case 'q': 970 if("query".equals(type)) return isQuery(value); 971 break; 972 case 's': 973 if("simple".equals(type)) return isSimpleValue(value); 974 if("struct".equals(type)) return isStruct(value); 975 if("ssn".equals(type)) return isSSN(value); 976 if("social_security_number".equals(type))return isSSN(value); 977 if("string".equals(type)) return isString(value); 978 break; 979 case 't': 980 if("telephone".equals(type)) return isPhone(value); 981 if("time".equals(type)) return isDateAdvanced(value,false); 982 break; 983 case 'u': 984 if("usdate".equals(type)) return isUSDate(value); 985 if("uuid".equals(type)) return isUUId(value); 986 if("url".equals(type)) return isURL(value); 987 break; 988 case 'v': 989 if("variablename".equals(type)) return isVariableName(Caster.toString(value,"")); 990 break; 991 case 'x': 992 if("xml".equals(type)) return isXML(value); // DIFF 23 993 break; 994 case 'z': 995 if("zip".equals(type)) return isZipCode(value); 996 if("zipcode".equals(type)) return isZipCode(value); 997 break; 998 } 999 throw new ExpressionException("invalid type ["+type+"], valid types are [any,array,binary,boolean,component,creditcard,date,time,email,eurodate,float,numeric,guid,integer,query,simple,ssn,string,struct,telephone,URL,UUID,USdate,variableName,zipcode]"); 1000 1001 } 1002 1003 /** 1004 * checks if a value is castable to a certain type 1005 * @param type any,array,boolean,binary, ... 1006 * @param o value to check 1007 * @param alsoPattern also check patterns like creditcards,email,phone ... 1008 * @param maxlength only used for email,url, string, ignored otherwise 1009 * @return 1010 */ 1011 public static boolean isCastableTo(String type, Object o, boolean alsoAlias, boolean alsoPattern, int maxlength) { 1012 1013 type=StringUtil.toLowerCase(type).trim(); 1014 if(type.length()>2) { 1015 char first=type.charAt(0); 1016 switch(first) { 1017 case 'a': 1018 if(type.equals("any")) { 1019 return true; 1020 } 1021 else if(type.equals("array")) { 1022 return isCastableToArray(o); 1023 } 1024 break; 1025 case 'b': 1026 if(type.equals("boolean") || (alsoAlias && type.equals("bool"))) { 1027 return isCastableToBoolean(o); 1028 } 1029 else if(type.equals("binary")) { 1030 return isCastableToBinary(o,true); 1031 } 1032 else if(alsoAlias && type.equals("bigint")) { 1033 return isCastableToNumeric(o); 1034 } 1035 else if(type.equals("base64")) { 1036 return Caster.toBase64(o,null,null)!=null; 1037 } 1038 break; 1039 case 'c': 1040 if(alsoPattern && type.equals("creditcard")) { 1041 return Caster.toCreditCard(o,null)!=null; 1042 } 1043 if(alsoPattern && type.equals("char")) { 1044 if(maxlength>-1) { 1045 String str = Caster.toString(o,null); 1046 if(str==null) return false; 1047 return str.length()<=maxlength; 1048 } 1049 return isCastableToString(o); 1050 } 1051 break; 1052 case 'd': 1053 if(type.equals("date")) { 1054 return isDateAdvanced(o, true); 1055 } 1056 else if(type.equals("datetime")) { 1057 return isDateAdvanced(o, true); 1058 } 1059 else if(alsoAlias && type.equals("double")) { 1060 return isCastableToNumeric(o); 1061 } 1062 else if(alsoAlias && type.equals("decimal")) { 1063 return Caster.toDecimal(o,null)!=null; 1064 } 1065 break; 1066 case 'e': 1067 if(alsoAlias && type.equals("eurodate")) { 1068 return isDateAdvanced(o, true); 1069 } 1070 else if(alsoPattern && type.equals("email")) { 1071 if(maxlength>-1) { 1072 String str = Caster.toEmail(o,null); 1073 if(str==null) return false; 1074 return str.length()<=maxlength; 1075 } 1076 return Caster.toEmail(o,null)!= null; 1077 } 1078 break; 1079 case 'f': 1080 if(alsoAlias && type.equals("float")) { 1081 return isCastableToNumeric(o); 1082 } 1083 if(type.equals("function")) { 1084 return isFunction(o); 1085 } 1086 break; 1087 case 'g': 1088 if(type.equals("guid")) { 1089 return isGUId(o); 1090 } 1091 break; 1092 case 'i': 1093 if(alsoAlias && (type.equals("integer") || type.equals("int"))) { 1094 return isCastableToNumeric(o); 1095 } 1096 break; 1097 case 'l': 1098 if(alsoAlias && type.equals("long")) { 1099 return isCastableToNumeric(o); 1100 } 1101 break; 1102 case 'n': 1103 if(type.equals("numeric")) { 1104 return isCastableToNumeric(o); 1105 } 1106 else if(type.equals("number")) { 1107 return isCastableToNumeric(o); 1108 } 1109 1110 if(alsoAlias) { 1111 if(type.equals("node")) return isXML(o); 1112 else if(type.equals("nvarchar") || type.equals("nchar")) { 1113 if(maxlength>-1) { 1114 String str = Caster.toString(o,null); 1115 if(str==null) return false; 1116 return str.length()<=maxlength; 1117 } 1118 return isCastableToString(o); 1119 } 1120 } 1121 1122 break; 1123 case 'o': 1124 if(type.equals("object")) { 1125 return true; 1126 } 1127 else if(alsoAlias && type.equals("other")) { 1128 return true; 1129 } 1130 break; 1131 case 'p': 1132 if(alsoPattern && type.equals("phone")) { 1133 return Caster.toPhone(o,null)!=null; 1134 } 1135 break; 1136 case 'q': 1137 if(type.equals("query")) { 1138 return isQuery(o); 1139 } 1140 1141 if(type.equals("querycolumn")) return isQueryColumn(o); 1142 1143 break; 1144 case 's': 1145 if(type.equals("string")) { 1146 if(maxlength>-1) { 1147 String str = Caster.toString(o,null); 1148 if(str==null) return false; 1149 return str.length()<=maxlength; 1150 } 1151 return isCastableToString(o); 1152 } 1153 else if(type.equals("struct")) { 1154 return isCastableToStruct(o); 1155 } 1156 else if(alsoAlias && type.equals("short")) { 1157 return isCastableToNumeric(o); 1158 } 1159 else if(alsoPattern && (type.equals("ssn") ||type.equals("social_security_number"))) { 1160 return Caster.toSSN(o,null)!=null; 1161 } 1162 break; 1163 case 't': 1164 if(type.equals("timespan")) { 1165 return Caster.toTimespan(o,null)!=null; 1166 } 1167 if(type.equals("time")) { 1168 return isDateAdvanced(o, true); 1169 } 1170 if(alsoPattern && type.equals("telephone")) { 1171 return Caster.toPhone(o,null)!=null; 1172 } 1173 1174 1175 if(alsoAlias && type.equals("timestamp")) return isDateAdvanced(o, true); 1176 if(alsoAlias && type.equals("text")) { 1177 if(maxlength>-1) { 1178 String str = Caster.toString(o,null); 1179 if(str==null) return false; 1180 return str.length()<=maxlength; 1181 } 1182 return isCastableToString(o); 1183 } 1184 1185 case 'u': 1186 if(type.equals("uuid")) { 1187 return isUUId(o); 1188 } 1189 if(alsoAlias && type.equals("usdate")) { 1190 return isDateAdvanced(o, true); 1191 } 1192 if(alsoPattern && type.equals("url")) { 1193 if(maxlength>-1) { 1194 String str = Caster.toURL(o,null); 1195 if(str==null) return false; 1196 return str.length()<=maxlength; 1197 } 1198 return Caster.toURL(o,null)!=null; 1199 } 1200 if(alsoAlias && type.equals("udf")) { 1201 return isFunction(o); 1202 } 1203 break; 1204 case 'v': 1205 if(type.equals("variablename")) { 1206 return isVariableName(o); 1207 } 1208 else if(type.equals("void")) { 1209 return isVoid(o);//Caster.toVoid(o,Boolean.TRUE)!=Boolean.TRUE; 1210 } 1211 else if(alsoAlias && type.equals("variable_name")) { 1212 return isVariableName(o); 1213 } 1214 else if(alsoAlias && type.equals("variable-name")) { 1215 return isVariableName(o); 1216 } 1217 if(type.equals("varchar")) { 1218 if(maxlength>-1) { 1219 String str = Caster.toString(o,null); 1220 if(str==null) return false; 1221 return str.length()<=maxlength; 1222 } 1223 return isCastableToString(o); 1224 } 1225 break; 1226 case 'x': 1227 if(type.equals("xml")) { 1228 return isXML(o); 1229 } 1230 break; 1231 case 'z': 1232 if(alsoPattern && (type.equals("zip") || type.equals("zipcode"))) { 1233 return Caster.toZip(o,null)!=null; 1234 } 1235 break; 1236 } 1237 } 1238 if(o instanceof Component) { 1239 Component comp=((Component)o); 1240 return comp.instanceOf(type); 1241 } 1242 if(isArrayType(type) && isArray(o)){ 1243 String t=type.substring(0,type.length()-2); 1244 Array arr = Caster.toArray(o,null); 1245 if(arr!=null){ 1246 Iterator<Object> it = arr.valueIterator(); 1247 while(it.hasNext()){ 1248 if(!isCastableTo(t, it.next(), alsoAlias,alsoPattern,-1)) 1249 return false; 1250 1251 } 1252 return true; 1253 } 1254 1255 } 1256 return false; 1257 } 1258 1259 1260 1261 private static boolean isArrayType(String type) { 1262 return type.endsWith("[]"); 1263 } 1264 1265 public static boolean isCastableTo(short type,String strType, Object o) { 1266 switch(type){ 1267 case CFTypes.TYPE_ANY: return true; 1268 case CFTypes.TYPE_STRING: return isCastableToString(o); 1269 case CFTypes.TYPE_BOOLEAN: return isCastableToBoolean(o); 1270 case CFTypes.TYPE_NUMERIC: return isCastableToNumeric(o); 1271 case CFTypes.TYPE_STRUCT: return isCastableToStruct(o); 1272 case CFTypes.TYPE_ARRAY: return isCastableToArray(o); 1273 case CFTypes.TYPE_QUERY: return isQuery(o); 1274 case CFTypes.TYPE_QUERY_COLUMN: return isQueryColumn(o); 1275 case CFTypes.TYPE_DATETIME: return isDateAdvanced(o, true); 1276 case CFTypes.TYPE_VOID: return isVoid(o);//Caster.toVoid(o,Boolean.TRUE)!=Boolean.TRUE; 1277 case CFTypes.TYPE_BINARY: return isCastableToBinary(o,true); 1278 case CFTypes.TYPE_TIMESPAN: return Caster.toTimespan(o,null)!=null; 1279 case CFTypes.TYPE_UUID: return isUUId(o); 1280 case CFTypes.TYPE_GUID: return isGUId(o); 1281 case CFTypes.TYPE_VARIABLE_NAME:return isVariableName(o); 1282 case CFTypes.TYPE_FUNCTION: return isFunction(o); 1283 case CFTypes.TYPE_XML: return isXML(o); 1284 } 1285 1286 if(o instanceof Component) { 1287 Component comp=((Component)o); 1288 return comp.instanceOf(strType); 1289 } 1290 if(isArrayType(strType) && isArray(o)){ 1291 String t=strType.substring(0,strType.length()-2); 1292 Array arr = Caster.toArray(o,null); 1293 if(arr!=null){ 1294 Iterator it = arr.valueIterator(); 1295 while(it.hasNext()){ 1296 if(!isCastableTo(type,t, it.next())) 1297 return false; 1298 1299 } 1300 return true; 1301 } 1302 1303 } 1304 1305 return false; 1306 } 1307 1308 public synchronized static boolean isDate(String str,Locale locale, TimeZone tz,boolean lenient) { 1309 str=str.trim(); 1310 tz=ThreadLocalPageContext.getTimeZone(tz); 1311 DateFormat[] df; 1312 1313 // get Calendar 1314 Calendar c=JREDateTimeUtil.getCalendar(locale); 1315 //synchronized(c){ 1316 // datetime 1317 df=FormatUtil.getDateTimeFormats(locale,tz,false);//dfc[FORMATS_DATE_TIME]; 1318 for(int i=0;i<df.length;i++) { 1319 try { 1320 synchronized(c) { 1321 df[i].parse(str); 1322 return true; 1323 } 1324 } 1325 catch (ParseException e) {} 1326 } 1327 // date 1328 df=FormatUtil.getDateFormats(locale,tz,false);//dfc[FORMATS_DATE]; 1329 for(int i=0;i<df.length;i++) { 1330 try { 1331 df[i].setTimeZone(tz); 1332 synchronized(c) { 1333 df[i].parse(str); 1334 return true; 1335 } 1336 } 1337 catch (ParseException e) {} 1338 } 1339 1340 // time 1341 df=FormatUtil.getTimeFormats(locale,tz,false);//dfc[FORMATS_TIME]; 1342 for(int i=0;i<df.length;i++) { 1343 try { 1344 df[i].setTimeZone(tz); 1345 synchronized(c) { 1346 df[i].parse(str); 1347 return true; 1348 } 1349 } 1350 catch (ParseException e) {} 1351 } 1352 //} 1353 if(lenient) return isDateSimple(str, false); 1354 return false; 1355 } 1356 1357 /** 1358 * Checks if number is valid (not infinity or NaN) 1359 * @param dbl 1360 * @return 1361 */ 1362 public static boolean isValid(double dbl) { 1363 return !Double.isNaN(dbl) && !Double.isInfinite(dbl); 1364 } 1365 }