001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.runtime.type; 020 021import java.util.ArrayList; 022import java.util.Iterator; 023import java.util.List; 024 025import lucee.commons.lang.CFTypes; 026import lucee.commons.lang.ExceptionUtil; 027import lucee.commons.lang.StringUtil; 028import lucee.runtime.Component; 029import lucee.runtime.ComponentImpl; 030import lucee.runtime.PageContext; 031import lucee.runtime.PageSource; 032import lucee.runtime.component.MemberSupport; 033import lucee.runtime.config.Config; 034import lucee.runtime.config.ConfigImpl; 035import lucee.runtime.dump.DumpData; 036import lucee.runtime.dump.DumpProperties; 037import lucee.runtime.dump.DumpTable; 038import lucee.runtime.exp.ApplicationException; 039import lucee.runtime.exp.ExpressionException; 040import lucee.runtime.exp.PageException; 041import lucee.runtime.interpreter.ref.Ref; 042import lucee.runtime.interpreter.ref.cast.Casting; 043import lucee.runtime.interpreter.ref.func.BIFCall; 044import lucee.runtime.interpreter.ref.literal.LFunctionValue; 045import lucee.runtime.interpreter.ref.literal.LString; 046import lucee.runtime.type.Collection.Key; 047import lucee.runtime.type.util.ArrayUtil; 048import lucee.runtime.type.util.CollectionUtil; 049import lucee.runtime.type.util.UDFUtil; 050import lucee.transformer.library.function.FunctionLib; 051import lucee.transformer.library.function.FunctionLibFunction; 052import lucee.transformer.library.function.FunctionLibFunctionArg; 053 054public class BIF extends MemberSupport implements UDFPlus { 055 056 private final FunctionLibFunction flf; 057 private short rtnType=CFTypes.TYPE_UNKNOW; 058 private ComponentImpl owner; 059 private final ConfigImpl ci; 060 private FunctionArgument[] args; 061 062 public BIF(Config config,String name) throws ApplicationException{ 063 super(Component.ACCESS_PUBLIC); 064 ci=(ConfigImpl) config; 065 FunctionLib fl = ci.getCombinedFLDs(); 066 flf = fl.getFunction(name); 067 068 // BIF not fuound 069 if(flf==null) { 070 Key[] keys = CollectionUtil.toKeys(fl.getFunctions().keySet()); 071 throw new ApplicationException(ExceptionUtil.similarKeyMessage(keys, name, "build in function", "build in functions", false)); 072 } 073 } 074 075 public BIF(Config config, FunctionLibFunction flf) { 076 super(Component.ACCESS_PUBLIC); 077 ci=(ConfigImpl) config; 078 this.flf=flf; 079 } 080 081 @Override 082 public FunctionArgument[] getFunctionArguments() { 083 if(args==null) { 084 ArrayList<FunctionLibFunctionArg> src = flf.getArg(); 085 args = new FunctionArgument[src.size()]; 086 087 String def; 088 int index=-1; 089 FunctionLibFunctionArg arg; 090 Iterator<FunctionLibFunctionArg> it = src.iterator(); 091 while(it.hasNext()){ 092 arg = it.next(); 093 def = arg.getDefaultValue(); 094 args[++index]=new FunctionArgumentImpl( 095 KeyImpl.init(arg.getName()) 096 , arg.getTypeAsString() 097 , arg.getType() 098 , arg.getRequired() 099 , def==null?FunctionArgument.DEFAULT_TYPE_NULL:FunctionArgument.DEFAULT_TYPE_LITERAL 100 , true 101 , arg.getName() 102 , arg.getDescription() 103 , null); 104 } 105 } 106 107 return args; 108 } 109 110 @Override 111 public Object callWithNamedValues(PageContext pageContext, Struct values, boolean doIncludePath) throws PageException { 112 ArrayList<FunctionLibFunctionArg> flfas = flf.getArg(); 113 Iterator<FunctionLibFunctionArg> it = flfas.iterator(); 114 FunctionLibFunctionArg arg; 115 Object val; 116 117 List<Ref> refs=new ArrayList<Ref>(); 118 while(it.hasNext()){ 119 arg=it.next(); 120 121 // match by name 122 val = values.get(arg.getName(),null); 123 124 //match by alias 125 if(val==null) { 126 String alias=arg.getAlias(); 127 if(!StringUtil.isEmpty(alias,true)) { 128 String[] aliases = lucee.runtime.type.util.ListUtil.trimItems(lucee.runtime.type.util.ListUtil.listToStringArray(alias,',')); 129 for(int x=0;x<aliases.length;x++){ 130 val = values.get(aliases[x],null); 131 if(val!=null) break; 132 } 133 } 134 } 135 136 if(val==null) { 137 if(arg.getRequired()) { 138 String[] names = flf.getMemberNames(); 139 String n=ArrayUtil.isEmpty(names)?"":names[0]; 140 throw new ExpressionException("missing required argument ["+arg.getName()+"] for build in function call ["+n+"]"); 141 } 142 } 143 else{ 144 refs.add(new Casting(arg.getTypeAsString(),arg.getType(),new LFunctionValue(new LString(arg.getName()),val))); 145 } 146 } 147 148 BIFCall call=new BIFCall(flf, refs.toArray(new Ref[refs.size()])); 149 return call.getValue(pageContext); 150 } 151 152 153 @Override 154 public Object call(PageContext pageContext, Object[] args, boolean doIncludePath) throws PageException { 155 ArrayList<FunctionLibFunctionArg> flfas = flf.getArg(); 156 FunctionLibFunctionArg flfa; 157 List<Ref> refs=new ArrayList<Ref>(); 158 for(int i=0;i<args.length;i++){ 159 if(i>=flfas.size()) throw new ApplicationException("too many Attributes in function call ["+flf.getName()+"]"); 160 flfa=flfas.get(i); 161 refs.add(new Casting(flfa.getTypeAsString(),flfa.getType(),args[i])); 162 } 163 BIFCall call=new BIFCall(flf, refs.toArray(new Ref[refs.size()])); 164 return call.getValue(pageContext); 165 } 166 167 @Override 168 public Object callWithNamedValues(PageContext pageContext, Key calledName, Struct values, boolean doIncludePath) throws PageException { 169 return callWithNamedValues(pageContext, values, doIncludePath); 170 } 171 172 @Override 173 public Object call(PageContext pageContext, Key calledName, Object[] args, boolean doIncludePath) throws PageException { 174 return call(pageContext, args, doIncludePath); 175 } 176 177 178 179 180 181 182 183 @Override 184 public DumpData toDumpData(PageContext pageContext, int maxlevel, DumpProperties dp) { 185 DumpTable dt= (DumpTable) UDFUtil.toDumpData(pageContext, maxlevel, dp,this,UDFUtil.TYPE_BIF); 186 //dt.setTitle(title); 187 return dt; 188 } 189 190 @Override 191 public UDF duplicate() { 192 return new BIF(ci, flf); 193 } 194 195 @Override 196 public Object duplicate(boolean deepCopy) { 197 return duplicate(); 198 } 199 200 @Override 201 public Component getOwnerComponent() { 202 return owner; 203 } 204 205 @Override 206 public String getDisplayName() { 207 return flf.getName(); 208 } 209 210 @Override 211 public String getHint() { 212 return flf.getDescription(); 213 } 214 215 @Override 216 public String getFunctionName() { 217 return flf.getName(); 218 } 219 220 @Override 221 public int getReturnType() { 222 if(rtnType==CFTypes.TYPE_UNKNOW) 223 rtnType=CFTypes.toShort(flf.getReturnTypeAsString(), false, CFTypes.TYPE_UNKNOW); 224 return rtnType; 225 } 226 227 @Override 228 public String getDescription() { 229 return flf.getDescription(); 230 } 231 232 @Override 233 public void setOwnerComponent(ComponentImpl owner) { 234 this.owner=owner; 235 } 236 237 @Override 238 public int getReturnFormat(int defaultFormat) { 239 return getReturnFormat(); 240 } 241 242 @Override 243 public int getReturnFormat() { 244 return UDF.RETURN_FORMAT_WDDX; 245 } 246 247 @Override 248 public String getReturnTypeAsString() { 249 return flf.getReturnTypeAsString(); 250 } 251 252 253 254 @Override 255 public Object getValue() { 256 return this; 257 } 258 259 @Override 260 public boolean getOutput() { 261 return false; 262 } 263 264 @Override 265 public Object getDefaultValue(PageContext pc, int index) throws PageException { 266 return null; 267 } 268 269 @Override 270 public Boolean getSecureJson() { 271 return null; 272 } 273 274 @Override 275 public Boolean getVerifyClient() { 276 return null; 277 } 278 279 @Override 280 public PageSource getPageSource() { 281 return null; 282 } 283 284 @Override 285 public int getIndex() { 286 return -1; 287 } 288 289 @Override 290 public Object getDefaultValue(PageContext pc, int index, Object defaultValue) throws PageException { 291 return null; 292 } 293 294 295 296 // MUST 297 @Override 298 public Struct getMetaData(PageContext pc) throws PageException { 299 // TODO Auto-generated method stub 300 return new StructImpl(); 301 } 302 303 @Override 304 public Object implementation(PageContext pageContext) throws Throwable { 305 // TODO Auto-generated method stub 306 return null; 307 } 308 309 310}