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