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().toLowerCase();
034                    if("range".equals(type))
035                            throw new FunctionException(pc,"isValid",1,"type","for [range] you have to define a min and max value");
036                    if("regex".equals(type) || "regular_expression".equals(type))
037                            throw new FunctionException(pc,"isValid",1,"type","for [regex] you have to define a pattern");
038    
039                    return Decision.isValid(type, value);
040            }
041            
042            /**
043             * regex check
044             * @param pc
045             * @param type
046             * @param value
047             * @param pattern_or_min
048             * @return
049             * @throws PageException 
050             */
051            public static boolean call(PageContext pc, String type, Object value, Object objPattern) throws PageException {
052                    type=type.trim().toLowerCase();
053                    if(!"regex".equals(type) && !"regular_expression".equals(type))
054                            throw new FunctionException(pc,"isValid",1,"type","wrong attribute count for type ["+type+"]");
055                    
056                    return regex(Caster.toString(value,null),Caster.toString(objPattern));
057            }
058            
059            
060            
061            
062            public static boolean regex(String value,String strPattern) {
063                    if(value==null)
064                            return false;
065                    
066                    try {
067                            Pattern pattern = new Perl5Compiler().compile(strPattern, Perl5Compiler.MULTILINE_MASK);
068                    PatternMatcherInput input = new PatternMatcherInput(value);
069                    return new Perl5Matcher().matches(input, pattern);
070                    } catch (MalformedPatternException e) {
071                            return false;
072                    }
073            }
074    
075            public static boolean call(PageContext pc, String type, Object value, Object objMin, Object objMax) throws PageException {
076                    
077                    // for named argument calls
078                    if(objMax==null) {
079                            if(objMin==null) return call(pc, type, value);
080                            return call(pc, type, value, objMin);
081                    }
082                    
083                    type=type.trim().toLowerCase();
084                    
085                    // numeric
086                    if("range".equals(type) || "integer".equals(type) || "float".equals(type) || "numeric".equals(type)  || "number".equals(type) ) {
087                    
088                            double number=Caster.toDoubleValue(value,Double.NaN);
089                            if(!Decision.isValid(number)) return false;
090                            
091                            double min=toRangeNumber(pc,objMin,3,"min");
092                            double max=toRangeNumber(pc,objMax,4,"max");
093                            
094                            
095                            return number>=min && number<=max;
096                    }
097                    else if("string".equals(type)){
098                            String str=Caster.toString(value,null);
099                            if(str==null) return false;
100                            
101                            double min=toRangeNumber(pc,objMin,3,"min");
102                            double max=toRangeNumber(pc,objMax,4,"max");
103                            
104                            return str.length()>=min && str.length()<=max;
105                    }
106                    
107                    else
108                            throw new FunctionException(pc,"isValid",1,"type","wrong attribute count for type ["+type+"]");
109                            
110            }
111    
112            private static double toRangeNumber(PageContext pc,Object objMin, int index,String name) throws FunctionException {
113                    double d=Caster.toDoubleValue(objMin,Double.NaN);
114                    if(!Decision.isValid(d))
115                            throw new FunctionException(pc,"isValid",index,name,"value must be numeric");
116                    return d;
117            }
118    }