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