001 package railo.runtime.type.util; 002 003 import java.util.ArrayList; 004 import java.util.Iterator; 005 import java.util.Map.Entry; 006 007 import railo.runtime.Page; 008 import railo.runtime.PageContext; 009 import railo.runtime.PagePlus; 010 import railo.runtime.PageSource; 011 import railo.runtime.exp.ApplicationException; 012 import railo.runtime.exp.PageException; 013 import railo.runtime.exp.PageExceptionImpl; 014 import railo.runtime.op.Decision; 015 import railo.runtime.type.Collection.Key; 016 import railo.runtime.type.KeyImpl; 017 import railo.runtime.type.Struct; 018 import railo.runtime.type.UDF; 019 import railo.runtime.type.UDFPlus; 020 import railo.transformer.library.function.FunctionLibFunction; 021 import railo.transformer.library.function.FunctionLibFunctionArg; 022 023 public class UDFUtil { 024 025 /** 026 * add detailed function documentation to the exception 027 * @param pe 028 * @param flf 029 */ 030 public static void addFunctionDoc(PageExceptionImpl pe,FunctionLibFunction flf) { 031 ArrayList<FunctionLibFunctionArg> args=flf.getArg(); 032 Iterator<FunctionLibFunctionArg> it = args.iterator(); 033 034 // Pattern 035 StringBuilder pattern=new StringBuilder(flf.getName()); 036 StringBuilder end=new StringBuilder(); 037 pattern.append("("); 038 FunctionLibFunctionArg arg; 039 int c=0; 040 while(it.hasNext()){ 041 arg = it.next(); 042 if(!arg.isRequired()) { 043 pattern.append(" ["); 044 end.append("]"); 045 } 046 if(c++>0)pattern.append(", "); 047 pattern.append(arg.getName()); 048 pattern.append(":"); 049 pattern.append(arg.getTypeAsString()); 050 051 } 052 pattern.append(end); 053 pattern.append("):"); 054 pattern.append(flf.getReturnTypeAsString()); 055 056 pe.setAdditional(KeyConstants._Pattern, pattern); 057 058 // Documentation 059 StringBuilder doc=new StringBuilder(flf.getDescription()); 060 StringBuilder req=new StringBuilder(); 061 StringBuilder opt=new StringBuilder(); 062 StringBuilder tmp; 063 doc.append("\n"); 064 065 it = args.iterator(); 066 while(it.hasNext()){ 067 arg = it.next(); 068 tmp=arg.isRequired()?req:opt; 069 070 tmp.append("- "); 071 tmp.append(arg.getName()); 072 tmp.append(" ("); 073 tmp.append(arg.getTypeAsString()); 074 tmp.append("): "); 075 tmp.append(arg.getDescription()); 076 tmp.append("\n"); 077 } 078 079 if(req.length()>0)doc.append("\nRequired:\n").append(req); 080 if(opt.length()>0)doc.append("\nOptional:\n").append(opt); 081 082 083 pe.setAdditional(KeyImpl.init("Documentation"), doc); 084 085 } 086 087 public static String callerHash(UDF udf, Object[] args, Struct values) throws ApplicationException { 088 StringBuilder sb=new StringBuilder(udf.getPageSource().getDisplayPath()) 089 .append(';') 090 .append(udf.getFunctionName()) 091 .append(';'); 092 093 if(values!=null) { 094 Iterator<Entry<Key, Object>> it = values.entryIterator(); 095 Entry<Key, Object> e; 096 while(it.hasNext()){ 097 e = it.next(); 098 if(!Decision.isSimpleValue(e.getValue())) throw new ApplicationException("only simple values are allowed as parameter for a function with cachedWithin"); 099 sb.append(e.getKey().getString()).append(':').append(e.getValue()).append(';'); 100 101 } 102 } 103 else if(args!=null){ 104 for(int i=0;i<args.length;i++){ 105 if(!Decision.isSimpleValue(args[i])) throw new ApplicationException("only simple values are allowed as parameter for a function with cachedWithin"); 106 sb.append(args[i]).append(';'); 107 108 } 109 } 110 return sb.toString(); 111 } 112 113 public static Object getDefaultValue(PageContext pc, PageSource ps, int udfIndex, int index, Object defaultValue) throws PageException { 114 Page p=ComponentUtil.getPage(pc,ps); 115 if(p instanceof PagePlus) return ((PagePlus)p).udfDefaultValue(pc,udfIndex,index,defaultValue); 116 Object rtn = p.udfDefaultValue(pc,udfIndex,index); 117 if(rtn==null) return defaultValue;// in that case it can make no diff between null and not existing, but this only happens with data from old ra files 118 return rtn; 119 } 120 121 122 public static Object getDefaultValue(PageContext pc, UDFPlus udf, int index, Object defaultValue) throws PageException { 123 Page p=ComponentUtil.getPage(pc,udf.getPageSource()); 124 if(p instanceof PagePlus) return ((PagePlus)p).udfDefaultValue(pc,udf.getIndex(),index,defaultValue); 125 Object rtn = p.udfDefaultValue(pc,udf.getIndex(),index); 126 if(rtn==null) return defaultValue;// in that case it can make no diff between null and not existing, but this only happens with data from old ra files 127 return rtn; 128 } 129 130 }