001 package railo.runtime.functions.decision; 002 003 import org.apache.oro.text.regex.MalformedPatternException; 004 import org.apache.oro.text.regex.Pattern; 005 import org.apache.oro.text.regex.PatternMatcherInput; 006 import org.apache.oro.text.regex.Perl5Compiler; 007 import org.apache.oro.text.regex.Perl5Matcher; 008 009 import railo.runtime.PageContext; 010 import railo.runtime.exp.ExpressionException; 011 import railo.runtime.exp.FunctionException; 012 import railo.runtime.exp.PageException; 013 import railo.runtime.ext.function.Function; 014 import railo.runtime.op.Caster; 015 import railo.runtime.op.Decision; 016 017 /** 018 * 019 */ 020 public final class IsValid implements Function { 021 022 private static final long serialVersionUID = -1383105304624662986L; 023 024 /** 025 * check for many diff types 026 * @param pc 027 * @param type 028 * @param value 029 * @return 030 * @throws ExpressionException 031 */ 032 public static boolean call(PageContext pc, String type, Object value) throws ExpressionException { 033 type=type.trim(); 034 035 if("range".equalsIgnoreCase(type)) 036 throw new FunctionException(pc,"isValid",1,"type","for [range] you have to define a min and max value"); 037 038 if("regex".equalsIgnoreCase(type) || "regular_expression".equalsIgnoreCase(type)) 039 throw new FunctionException(pc,"isValid",1,"type","for [regex] you have to define a pattern"); 040 041 return Decision.isValid(type, value); 042 } 043 044 /** 045 * regex check 046 * @param pc 047 * @param type 048 * @param value 049 * @param objPattern 050 * @return 051 * @throws PageException 052 */ 053 public static boolean call(PageContext pc, String type, Object value, Object objPattern) throws PageException { 054 type=type.trim(); 055 056 if(!"regex".equalsIgnoreCase(type) && !"regular_expression".equalsIgnoreCase(type)) 057 throw new FunctionException(pc,"isValid",1,"type","wrong attribute count for type ["+type+"]"); 058 059 return regex(Caster.toString(value,null),Caster.toString(objPattern)); 060 } 061 062 063 064 065 public static boolean regex(String value,String strPattern) { 066 if(value==null) 067 return false; 068 069 try { 070 Pattern pattern = new Perl5Compiler().compile(strPattern, Perl5Compiler.MULTILINE_MASK); 071 PatternMatcherInput input = new PatternMatcherInput(value); 072 return new Perl5Matcher().matches(input, pattern); 073 } catch (MalformedPatternException e) { 074 return false; 075 } 076 } 077 078 public static boolean call(PageContext pc, String type, Object value, Object objMin, Object objMax) throws PageException { 079 080 // for named argument calls 081 if(objMax==null) { 082 if(objMin==null) return call(pc, type, value); 083 return call(pc, type, value, objMin); 084 } 085 086 type=type.trim().toLowerCase(); 087 088 // numeric 089 if("range".equals(type) || "integer".equals(type) || "float".equals(type) || "numeric".equals(type) || "number".equals(type) ) { 090 091 double number=Caster.toDoubleValue(value,Double.NaN); 092 if(!Decision.isValid(number)) return false; 093 094 double min=toRangeNumber(pc,objMin,3,"min"); 095 double max=toRangeNumber(pc,objMax,4,"max"); 096 097 098 return number>=min && number<=max; 099 } 100 else if("string".equals(type)){ 101 String str=Caster.toString(value,null); 102 if(str==null) return false; 103 104 double min=toRangeNumber(pc,objMin,3,"min"); 105 double max=toRangeNumber(pc,objMax,4,"max"); 106 107 return str.length()>=min && str.length()<=max; 108 } 109 110 else 111 throw new FunctionException(pc,"isValid",1,"type","wrong attribute count for type ["+type+"]"); 112 113 } 114 115 private static double toRangeNumber(PageContext pc,Object objMin, int index,String name) throws FunctionException { 116 double d=Caster.toDoubleValue(objMin,Double.NaN); 117 if(!Decision.isValid(d)) 118 throw new FunctionException(pc,"isValid",index,name,"value must be numeric"); 119 return d; 120 } 121 }