001    /**
002     * Implements the CFML Function getfunctiondescription
003     */
004    package railo.runtime.functions.other;
005    
006    import java.util.ArrayList;
007    
008    import railo.commons.lang.CFTypes;
009    import railo.commons.lang.StringUtil;
010    import railo.runtime.PageContext;
011    import railo.runtime.config.ConfigImpl;
012    import railo.runtime.exp.ExpressionException;
013    import railo.runtime.exp.PageException;
014    import railo.runtime.ext.function.Function;
015    import railo.runtime.functions.system.CFFunction;
016    import railo.runtime.op.Caster;
017    import railo.runtime.type.Array;
018    import railo.runtime.type.ArrayImpl;
019    import railo.runtime.type.Collection;
020    import railo.runtime.type.Collection.Key;
021    import railo.runtime.type.FunctionArgument;
022    import railo.runtime.type.KeyImpl;
023    import railo.runtime.type.Struct;
024    import railo.runtime.type.StructImpl;
025    import railo.runtime.type.UDFImpl;
026    import railo.runtime.type.util.KeyConstants;
027    import railo.transformer.library.function.FunctionLib;
028    import railo.transformer.library.function.FunctionLibFunction;
029    import railo.transformer.library.function.FunctionLibFunctionArg;
030    import railo.transformer.library.tag.TagLibFactory;
031    
032    public final class GetFunctionData implements Function {
033            private static final Collection.Key SOURCE = KeyConstants._source;
034            private static final Collection.Key RETURN_TYPE = KeyImpl.intern("returnType");
035            private static final Collection.Key ARGUMENT_TYPE = KeyImpl.intern("argumentType");
036            private static final Collection.Key ARG_MIN = KeyImpl.intern("argMin");
037            private static final Collection.Key ARG_MAX = KeyImpl.intern("argMax");
038            
039            public static Struct call(PageContext pc , String strFunctionName) throws PageException {
040                    FunctionLib[] flds;
041                    flds = ((ConfigImpl)pc.getConfig()).getFLDs();
042    
043                    
044                    FunctionLibFunction function=null;
045                    for(int i=0;i<flds.length;i++) {
046                            function = flds[i].getFunction(strFunctionName.toLowerCase());
047                            if(function!=null)break;
048                    }
049                    if(function == null) throw new ExpressionException("function ["+strFunctionName+"] is not a built in function");
050    
051            //sct.set("returnTypeClass",_class(function.getCazz()));
052            //sct.set("class",__class(function.getCazz()));
053            
054                    
055                    
056                    // CFML Based Function
057                    Class clazz=null;
058                    try{
059                            clazz=function.getClazz();
060                    }
061                    catch(Throwable t){}
062                    if(clazz==railo.runtime.functions.system.CFFunction.class){
063                            return cfmlBasedFunction(pc,function);
064                    }
065                    return javaBasedFunction(function);
066                    
067                    
068                    
069            }
070    
071            private static Struct javaBasedFunction(FunctionLibFunction function) throws PageException {
072                    Struct sct=new StructImpl();
073                    sct.set(KeyConstants._name,function.getName());
074            sct.set(KeyConstants._status,TagLibFactory.toStatus(function.getStatus()));
075                    sct.set(KeyConstants._description,StringUtil.emptyIfNull(function.getDescription()));
076            sct.set(RETURN_TYPE,StringUtil.emptyIfNull(function.getReturnTypeAsString()));
077            sct.set(ARGUMENT_TYPE,StringUtil.emptyIfNull(function.getArgTypeAsString()));
078            sct.set(ARG_MIN,Caster.toDouble(function.getArgMin()));
079            sct.set(ARG_MAX,Caster.toDouble(function.getArgMax()));
080            sct.set(KeyConstants._type,"java");
081                    String mm = function.getMemberName();
082            if(mm!=null && function.getMemberType()!=CFTypes.TYPE_UNKNOW) {
083                    StructImpl mem = new StructImpl();
084                    sct.set(KeyConstants._member, mem);
085                    mem.set(KeyConstants._name,mm);
086                    mem.set(KeyConstants._chaining,Caster.toBoolean(function.getMemberChaining()));
087                mem.set(KeyConstants._type, function.getMemberTypeAsString());
088            }
089                    
090                    Array _args=new ArrayImpl();
091                    sct.set(KeyConstants._arguments,_args);
092                    if(function.getArgType()!=FunctionLibFunction.ARG_DYNAMIC){
093                            ArrayList<FunctionLibFunctionArg> args = function.getArg();
094                            for(int i=0;i<args.size();i++) {
095                                    FunctionLibFunctionArg arg=args.get(i);
096                                    Struct _arg=new StructImpl();
097                                    _arg.set(KeyConstants._required,arg.getRequired()?Boolean.TRUE:Boolean.FALSE);
098                                    _arg.set(KeyConstants._type,StringUtil.emptyIfNull(arg.getTypeAsString()));
099                                    _arg.set(KeyConstants._name,StringUtil.emptyIfNull(arg.getName()));
100                                    _arg.set(KeyConstants._status,TagLibFactory.toStatus(arg.getStatus()));
101                                    _arg.set(KeyConstants._description,StringUtil.toStringEmptyIfNull(arg.getDescription()));
102                                    
103                                    
104                                    _args.append(_arg);
105                            }
106                    }
107                    return sct;
108            }
109    
110            private static Struct cfmlBasedFunction(PageContext pc, FunctionLibFunction function) throws PageException {
111                    Struct sct=new StructImpl();
112                    ArrayList<FunctionLibFunctionArg> args = function.getArg();
113                    
114                    String filename = Caster.toString(args.get(0).getDefaultValue());
115                    Key name = KeyImpl.toKey(args.get(1).getDefaultValue());
116                    boolean isWeb = Caster.toBooleanValue(args.get(2).getDefaultValue());
117                    UDFImpl udf = (UDFImpl) CFFunction.loadUDF(pc, filename, name, isWeb);
118                    
119                    sct.set(KeyConstants._name,function.getName());
120            sct.set(ARGUMENT_TYPE,"fixed");
121            sct.set(KeyConstants._description,StringUtil.emptyIfNull(udf.getHint()));
122            sct.set(RETURN_TYPE,StringUtil.emptyIfNull(udf.getReturnTypeAsString()));
123            sct.set(KeyConstants._type,"cfml");
124            sct.set(SOURCE,udf.getPageSource().getDisplayPath());
125                    sct.set(KeyConstants._status,"implemeted");
126                    
127                    
128            FunctionArgument[] fas = udf.getFunctionArguments();
129            Array _args=new ArrayImpl();
130                    sct.set(KeyConstants._arguments,_args);
131            int min=0,max=0;
132                    for(int i=0;i<fas.length;i++) {
133                    FunctionArgument fa=fas[i];
134                    Struct meta = fa.getMetaData();
135                    
136                            Struct _arg=new StructImpl();
137                            if(fa.isRequired()) min++;
138                            max++;
139                            _arg.set(KeyConstants._required,fa.isRequired()?Boolean.TRUE:Boolean.FALSE);
140                            _arg.set(KeyConstants._type,StringUtil.emptyIfNull(fa.getTypeAsString()));
141                            _arg.set(KeyConstants._name,StringUtil.emptyIfNull(fa.getName()));
142                            _arg.set(KeyConstants._description,StringUtil.emptyIfNull(fa.getHint()));
143                            
144                            String status;
145                            if(meta==null)status="implemeted";
146                            else status=TagLibFactory.toStatus(TagLibFactory.toStatus(Caster.toString(meta.get(KeyConstants._status,"implemeted"))));
147                            
148                            _arg.set(KeyConstants._status,status);
149                            
150                            _args.append(_arg);
151                    }
152            sct.set(ARG_MIN,Caster.toDouble(min));
153            sct.set(ARG_MAX,Caster.toDouble(max));
154            
155            
156                    return sct;
157            }
158    }