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.scope; 020 021import java.util.ArrayList; 022import java.util.Iterator; 023import java.util.List; 024 025import lucee.commons.lang.ExceptionUtil; 026import lucee.runtime.ComponentScope; 027import lucee.runtime.PageContext; 028import lucee.runtime.PageContextImpl; 029import lucee.runtime.config.Config; 030import lucee.runtime.config.ConfigImpl; 031import lucee.runtime.config.NullSupportHelper; 032import lucee.runtime.dump.DumpData; 033import lucee.runtime.dump.DumpProperties; 034import lucee.runtime.exp.ExpressionException; 035import lucee.runtime.exp.PageException; 036import lucee.runtime.op.Duplicator; 037import lucee.runtime.type.Collection; 038import lucee.runtime.type.KeyImpl; 039import lucee.runtime.type.Query; 040import lucee.runtime.type.QueryColumn; 041import lucee.runtime.type.Struct; 042import lucee.runtime.type.StructImpl; 043import lucee.runtime.type.UDF; 044import lucee.runtime.type.UDFPlus; 045import lucee.runtime.type.dt.DateTime; 046import lucee.runtime.type.util.KeyConstants; 047import lucee.runtime.type.util.StructSupport; 048import lucee.runtime.util.QueryStack; 049import lucee.runtime.util.QueryStackImpl; 050 051/** 052 * Undefined Scope 053 */ 054public final class UndefinedImpl extends StructSupport implements Undefined { 055 056 private static final long serialVersionUID = -5626787508494702023L; 057 058 private Scope[] scopes; 059 private QueryStackImpl qryStack=new QueryStackImpl(); 060 private Variables variable; 061 private boolean allowImplicidQueryCall; 062 private boolean checkArguments; 063 064 065 066 private boolean localAlways; 067 private short type; 068 private boolean isInit; 069 private Local local; 070 private Argument argument; 071 private PageContextImpl pc; 072 private boolean debug; 073 074 /** 075 * constructor of the class 076 * @param pageContextImpl 077 * @param type type of the undefined scope (ServletConfigImpl.SCOPE_STRICT;ServletConfigImpl.SCOPE_SMALL;ServletConfigImpl.SCOPE_STANDART) 078 */ 079 public UndefinedImpl(PageContextImpl pc, short type) { 080 this.type=type; 081 this.pc=pc; 082 } 083 084 085 @Override 086 public Local localScope() { 087 return local; 088 } 089 090 @Override 091 public Argument argumentsScope() { 092 return argument; 093 } 094 095 @Override 096 public Variables variablesScope() { 097 return variable; 098 } 099 100 @Override 101 public int setMode(int mode) { 102 int m=Undefined.MODE_NO_LOCAL_AND_ARGUMENTS; 103 if(checkArguments) { 104 if(localAlways)m=Undefined.MODE_LOCAL_OR_ARGUMENTS_ALWAYS; 105 else m=Undefined.MODE_LOCAL_OR_ARGUMENTS_ONLY_WHEN_EXISTS; 106 } 107 108 checkArguments=mode!=Undefined.MODE_NO_LOCAL_AND_ARGUMENTS; 109 localAlways=mode==Undefined.MODE_LOCAL_OR_ARGUMENTS_ALWAYS; 110 return m; 111 } 112 113 public boolean getLocalAlways(){ 114 return localAlways; 115 } 116 117 118 @Override 119 public void setFunctionScopes(Local local, Argument argument) { 120 this.local=local; 121 this.argument=argument; 122 } 123 124 @Override 125 public QueryStack getQueryStack() { 126 return qryStack; 127 } 128 129 @Override 130 public void setQueryStack(QueryStack qryStack) { 131 this.qryStack=(QueryStackImpl) qryStack; 132 } 133 134 @Override 135 public void addQuery(Query qry) { 136 if(allowImplicidQueryCall) 137 qryStack.addQuery(qry); 138 } 139 140 @Override 141 public void removeQuery() { 142 if(allowImplicidQueryCall) 143 qryStack.removeQuery(); 144 } 145 146 @Override 147 public int size() { 148 return variable.size(); 149 } 150 151 @Override 152 public Collection.Key[] keys() { 153 return variable.keys(); 154 } 155 156 @Override 157 public Object remove(Collection.Key key) throws PageException { 158 if(checkArguments && local.containsKey(key)) 159 return local.remove(key); 160 return variable.remove(key); 161 } 162 163 @Override 164 public Object removeEL(Collection.Key key) { 165 if(checkArguments && local.containsKey(key)) 166 return local.removeEL(key); 167 return variable.removeEL(key); 168 } 169 170 @Override 171 public void clear() { 172 variable.clear(); 173 } 174 175 public Object get(Collection.Key key) throws PageException { 176 //print.e(); 177 Object rtn; 178 if(checkArguments) { 179 rtn=local.get(key,NullSupportHelper.NULL()); 180 if(rtn!=NullSupportHelper.NULL()) return rtn; 181 182 rtn=argument.getFunctionArgument(key,NullSupportHelper.NULL()); 183 if(rtn!=NullSupportHelper.NULL()) { 184 if(debug) debugCascadedAccess(pc,argument.getTypeAsString(), key); 185 return rtn; 186 } 187 } 188 189 // get data from queries 190 if(allowImplicidQueryCall && !qryStack.isEmpty()) { 191 rtn=qryStack.getDataFromACollection(pc,key,NullSupportHelper.NULL()); 192 if(rtn!=NullSupportHelper.NULL()) { 193 if(debug) debugCascadedAccess(pc,"query", key); 194 if(!NullSupportHelper.full() && rtn==null) return ""; 195 return rtn; 196 } 197 } 198 199 // variable 200 rtn=variable.get(key,NullSupportHelper.NULL()); 201 if(rtn!=NullSupportHelper.NULL()) { 202 if(debug && checkArguments) debugCascadedAccess(pc,variable,rtn, key); 203 return rtn; 204 } 205 206 // thread scopes 207 if(pc.hasFamily()) { 208 rtn = pc.getThreadScope(key,NullSupportHelper.NULL()); 209 if(rtn!=NullSupportHelper.NULL()) { 210 if(debug) debugCascadedAccess(pc,"thread", key); 211 return rtn; 212 } 213 } 214 215 // get a scope value 216 for(int i=0;i<scopes.length;i++) { 217 rtn=scopes[i].get(key,NullSupportHelper.NULL()); 218 if(rtn!=NullSupportHelper.NULL()) { 219 if(debug) debugCascadedAccess(pc,scopes[i].getTypeAsString(),key); 220 return rtn; 221 } 222 } 223 if(pc.getConfig().debug()) 224 throw new ExpressionException(ExceptionUtil.similarKeyMessage(this, key.getString(), "key", "keys",false)); 225 226 throw new ExpressionException("variable ["+key.getString()+"] doesn't exist"); 227 } 228 229 public static void debugCascadedAccess(PageContext pc,Variables var, Object value, Collection.Key key) { 230 if(var instanceof ComponentScope){ 231 if(key.equals(KeyConstants._THIS) || key.equals(KeyConstants._SUPER)) return; 232 if(value instanceof UDF) { 233 return; 234 } 235 } 236 237 debugCascadedAccess(pc,"variables", key); 238 } 239 240 public static void debugCascadedAccess(PageContext pc,String name, Collection.Key key) { 241 if(pc!=null)pc.getDebugger().addImplicitAccess(name,key.getString()); 242 } 243 244 @Override 245 public Object getCollection(String key) throws PageException { 246 return getCollection(KeyImpl.init(key)); 247 } 248 249 public Struct getScope(Collection.Key key) { 250 Object rtn=null; 251 Struct sct=new StructImpl(Struct.TYPE_LINKED); 252 253 if(checkArguments) { 254 rtn=local.get(key,NullSupportHelper.NULL()); 255 if(rtn!=NullSupportHelper.NULL()) sct.setEL(KeyConstants._local, rtn); 256 rtn=argument.getFunctionArgument(key,NullSupportHelper.NULL()); 257 if(rtn!=NullSupportHelper.NULL()) sct.setEL(KeyConstants._arguments, rtn); 258 } 259 260 // get data from queries 261 if(allowImplicidQueryCall && !qryStack.isEmpty()) { 262 rtn=qryStack.getColumnFromACollection(key); 263 if(rtn!=null) sct.setEL(KeyConstants._query, rtn); 264 } 265 266 // variable 267 rtn=variable.get(key,NullSupportHelper.NULL()); 268 if(rtn!=NullSupportHelper.NULL()) { 269 sct.setEL(KeyConstants._variables, rtn); 270 } 271 272 // thread scopes 273 if(pc.hasFamily()) { 274 rtn = pc.getThreadScope(key,NullSupportHelper.NULL()); 275 if(rtn!=NullSupportHelper.NULL()) sct.setEL(KeyConstants._thread, rtn); 276 } 277 278 // get a scope value 279 for(int i=0;i<scopes.length;i++) { 280 rtn=scopes[i].get(key,NullSupportHelper.NULL()); 281 if(rtn!=NullSupportHelper.NULL()) { 282 sct.setEL(KeyImpl.init(scopes[i].getTypeAsString()), rtn); 283 } 284 } 285 return sct; 286 } 287 288 /** 289 * returns the scope that contains a specific key 290 * @param key 291 * @return 292 */ 293 public Collection getScopeFor(Collection.Key key, Scope defaultValue) { 294 Object rtn=null; 295 296 if(checkArguments) { 297 rtn=local.get(key,NullSupportHelper.NULL()); 298 if(rtn!=NullSupportHelper.NULL()) return local;; 299 rtn=argument.getFunctionArgument(key,NullSupportHelper.NULL()); 300 if(rtn!=NullSupportHelper.NULL()) return argument; 301 } 302 303 // get data from queries 304 if(allowImplicidQueryCall && !qryStack.isEmpty()) { 305 QueryColumn qc = qryStack.getColumnFromACollection(key); 306 if(qc!=null) return (Query)qc.getParent(); 307 } 308 309 // variable 310 rtn=variable.get(key,NullSupportHelper.NULL()); 311 if(rtn!=NullSupportHelper.NULL()) { 312 return variable; 313 } 314 315 // thread scopes 316 if(pc.hasFamily()) { 317 Threads t = (Threads) pc.getThreadScope(key,NullSupportHelper.NULL()); 318 if(rtn!=NullSupportHelper.NULL()) return t; 319 } 320 321 // get a scope value 322 for(int i=0;i<scopes.length;i++) { 323 rtn=scopes[i].get(key,NullSupportHelper.NULL()); 324 if(rtn!=NullSupportHelper.NULL()) { 325 return scopes[i]; 326 } 327 } 328 return defaultValue; 329 } 330 331 332 /** 333 * return a list of String with the scope names 334 * @param key 335 * @return 336 */ 337 public List<String> getScopeNames() { 338 List<String> scopeNames=new ArrayList<String>(); 339 340 if(checkArguments) { 341 scopeNames.add("local"); 342 scopeNames.add("arguments"); 343 } 344 scopeNames.add("variables"); 345 346 // thread scopes 347 if(pc.hasFamily()) { 348 String[] names = pc.getThreadScopeNames(); 349 for(int i=0;i<names.length;i++)scopeNames.add(i,names[i]); 350 } 351 352 for(int i=0;i<scopes.length;i++) { 353 scopeNames.add((scopes[i]).getTypeAsString()); 354 } 355 return scopeNames; 356 } 357 358 public Object getCollection(Key key) throws PageException { 359 Object rtn=null; 360 361 if(checkArguments) { 362 rtn=local.get(key,NullSupportHelper.NULL()); 363 if(rtn!=NullSupportHelper.NULL()) return rtn; 364 rtn=argument.getFunctionArgument(key,NullSupportHelper.NULL()); 365 if(rtn!=NullSupportHelper.NULL()) { 366 if(debug)debugCascadedAccess(pc,argument.getTypeAsString(), key); 367 return rtn; 368 } 369 } 370 371 // get data from queries 372 if(allowImplicidQueryCall && !qryStack.isEmpty()) { 373 rtn=qryStack.getColumnFromACollection(key); 374 if(rtn!=null) { 375 if(debug)debugCascadedAccess(pc,"query", key); 376 return rtn; 377 } 378 } 379 380 // variable 381 rtn=variable.get(key,NullSupportHelper.NULL()); 382 if(rtn!=NullSupportHelper.NULL()) { 383 if(debug && checkArguments) debugCascadedAccess(pc,variable,rtn, key); 384 return rtn; 385 } 386 387 // thread scopes 388 if(pc.hasFamily()) { 389 rtn = pc.getThreadScope(key,NullSupportHelper.NULL()); 390 if(rtn!=NullSupportHelper.NULL()) { 391 if(debug) debugCascadedAccess(pc,"thread", key); 392 return rtn; 393 } 394 } 395 396 // get a scope value 397 for(int i=0;i<scopes.length;i++) { 398 rtn=scopes[i].get(key,NullSupportHelper.NULL()); 399 if(rtn!=NullSupportHelper.NULL()) { 400 if(debug)debugCascadedAccess(pc,scopes[i].getTypeAsString(),key); 401 return rtn; 402 } 403 } 404 throw new ExpressionException("variable ["+key.getString()+"] doesn't exist"); 405 } 406 407 public Object get(Collection.Key key, Object defaultValue) { 408 Object rtn=null; 409 if(checkArguments) { 410 rtn=local.get(key,NullSupportHelper.NULL()); 411 if(rtn!=NullSupportHelper.NULL()) return rtn; 412 413 rtn=argument.getFunctionArgument(key,NullSupportHelper.NULL()); 414 if(rtn!=NullSupportHelper.NULL()) { 415 if(debug) debugCascadedAccess(pc,argument.getTypeAsString(), key); 416 return rtn; 417 } 418 } 419 420 // get data from queries 421 if(allowImplicidQueryCall && !qryStack.isEmpty()) { 422 rtn=qryStack.getDataFromACollection(pc,key,NullSupportHelper.NULL()); 423 if(rtn!=NullSupportHelper.NULL()) { 424 if(debug) debugCascadedAccess(pc,"query", key); 425 return rtn; 426 } 427 } 428 429 // variable 430 rtn=variable.get(key,NullSupportHelper.NULL()); 431 if(rtn!=NullSupportHelper.NULL()) { 432 if(debug && checkArguments) debugCascadedAccess(pc,variable, rtn, key); 433 return rtn; 434 } 435 436 // thread scopes 437 if(pc.hasFamily()) { 438 rtn = pc.getThreadScope(key,NullSupportHelper.NULL()); 439 if(rtn!=NullSupportHelper.NULL()) { 440 if(debug && checkArguments) debugCascadedAccess(pc,"thread", key); 441 return rtn; 442 } 443 } 444 445 // get a scope value 446 for(int i=0;i<scopes.length;i++) { 447 rtn=scopes[i].get(key,NullSupportHelper.NULL()); 448 if(rtn!=NullSupportHelper.NULL()) { 449 if(debug) debugCascadedAccess(pc,scopes[i].getTypeAsString(), key); 450 return rtn; 451 } 452 } 453 454 return defaultValue; 455 } 456 457 458 @Override 459 public Object getCascading(String strKey) { 460 return getCascading(KeyImpl.init(strKey)); 461 } 462 463 464 @Override 465 public Object getCascading(Collection.Key key) { 466 throw new RuntimeException("this method is no longer supported, use getCascading(Collection.Key key, Object defaultValue) instead"); 467 } 468 469 // FUTURE add to interface and set above to deprecated 470 public Object getCascading(Collection.Key key, Object defaultValue) { 471 Object rtn; 472 473 // get a scope value 474 for(int i=0;i<scopes.length;i++) { 475 rtn=scopes[i].get(key,NullSupportHelper.NULL()); 476 if(rtn!=NullSupportHelper.NULL()) { 477 return rtn; 478 } 479 } 480 return defaultValue; 481 } 482 483 @Override 484 public Object setEL(Collection.Key key, Object value) { 485 if(checkArguments) { 486 if(localAlways || local.containsKey(key)) return local.setEL(key,value); 487 if(argument.containsFunctionArgumentKey(key)) { 488 if(debug)debugCascadedAccess(pc,argument.getTypeAsString(), key); 489 return argument.setEL(key,value); 490 } 491 } 492 493 if(debug && checkArguments)debugCascadedAccess(pc,variable.getTypeAsString(), key); 494 return variable.setEL(key,value); 495 } 496 497 @Override 498 public Object set(Collection.Key key, Object value) throws PageException { 499 if(checkArguments) { 500 if(localAlways || local.containsKey(key)) return local.set(key,value); 501 if(argument.containsFunctionArgumentKey(key)) { 502 if(debug)debugCascadedAccess(pc,argument.getTypeAsString(), key); 503 return argument.set(key,value); 504 } 505 506 } 507 if(debug && checkArguments)debugCascadedAccess(pc,variable.getTypeAsString(), key); 508 return variable.set(key,value); 509 } 510 511 @Override 512 public DumpData toDumpData(PageContext pageContext, int maxlevel, DumpProperties dp) { 513 return variable.toDumpData(pageContext, maxlevel,dp); 514 } 515 516 @Override 517 public Iterator<Collection.Key> keyIterator() { 518 return variable.keyIterator(); 519 } 520 521 @Override 522 public Iterator<String> keysAsStringIterator() { 523 return variable.keysAsStringIterator(); 524 } 525 526 @Override 527 public Iterator<Entry<Key, Object>> entryIterator() { 528 return variable.entryIterator(); 529 } 530 531 @Override 532 public Iterator<Object> valueIterator() { 533 return variable.valueIterator(); 534 } 535 536 @Override 537 public boolean isInitalized() { 538 return isInit; 539 } 540 541 @Override 542 public void initialize(PageContext pc) { 543 //if(isInitalized()) return; 544 isInit=true; 545 variable=pc.variablesScope(); 546 argument=pc.argumentsScope(); 547 local=pc.localScope(); 548 allowImplicidQueryCall=pc.getConfig().allowImplicidQueryCall(); 549 type=((PageContextImpl)pc).getScopeCascadingType(); 550 debug=pc.getConfig().debug() && ((ConfigImpl)pc.getConfig()).hasDebugOptions(ConfigImpl.DEBUG_IMPLICIT_ACCESS); 551 552 // Strict 553 if(type==Config.SCOPE_STRICT) { 554 //print.ln("strict"); 555 scopes=new Scope[] {}; 556 } 557 // small 558 else if(type==Config.SCOPE_SMALL) { 559 //print.ln("small"); 560 if(pc.getConfig().mergeFormAndURL()) { 561 scopes=new Scope[] { 562 pc.formScope() 563 }; 564 } 565 else { 566 scopes=new Scope[] { 567 pc.urlScope(), 568 pc.formScope() 569 }; 570 } 571 } 572 // standard 573 else { 574 reinitialize( pc); 575 } 576 577 578 } 579 580 public void reinitialize(PageContext pc) { 581 if(type!=Config.SCOPE_STANDARD) return; 582 Client cs = pc.clientScopeEL(); 583// print.ln("standard"); 584 if(pc.getConfig().mergeFormAndURL()) { 585 scopes=new Scope[cs==null?3:4]; 586 scopes[0]=pc.cgiScope(); 587 scopes[1]=pc.formScope(); 588 scopes[2]=pc.cookieScope(); 589 if(cs!=null)scopes[3]=cs; 590 } 591 else { 592 scopes=new Scope[cs==null?4:5]; 593 scopes[0]=pc.cgiScope(); 594 scopes[1]=pc.urlScope(); 595 scopes[2]=pc.formScope(); 596 scopes[3]=pc.cookieScope(); 597 if(cs!=null)scopes[4]=cs; 598 } 599 } 600 601 602 @Override 603 public final void release() { 604 isInit=false; 605 argument=null; 606 local=null; 607 variable=null; 608 scopes=null; 609 checkArguments=false; 610 localAlways=false; 611 if(allowImplicidQueryCall)qryStack.clear(); 612 } 613 614 @Override 615 public final void release(PageContext pc) { 616 isInit=false; 617 argument=null; 618 local=null; 619 variable=null; 620 scopes=null; 621 checkArguments=false; 622 localAlways=false; 623 if(allowImplicidQueryCall)qryStack.clear(); 624 } 625 626 @Override 627 public Collection duplicate(boolean deepCopy) { 628 UndefinedImpl dupl = new UndefinedImpl(pc, type); 629 dupl.allowImplicidQueryCall=allowImplicidQueryCall; 630 dupl.checkArguments=checkArguments; 631 dupl.argument=deepCopy?(Argument)Duplicator.duplicate(argument,deepCopy):argument; 632 dupl.isInit=isInit; 633 dupl.local=deepCopy?(Local)Duplicator.duplicate(local,deepCopy):local; 634 dupl.localAlways=localAlways; 635 dupl.qryStack= (deepCopy?(QueryStackImpl)Duplicator.duplicate(qryStack,deepCopy):qryStack); 636 637 dupl.variable=deepCopy?(Variables)Duplicator.duplicate(variable,deepCopy):variable; 638 dupl.pc=pc; 639 dupl.debug=debug; 640 641 // scopes 642 if(deepCopy) { 643 dupl.scopes=new Scope[scopes.length]; 644 for(int i=0;i<scopes.length;i++) { 645 dupl.scopes[i]=(Scope)Duplicator.duplicate(scopes[i],deepCopy); 646 } 647 } 648 else dupl.scopes=scopes; 649 650 return dupl; 651 } 652 653 654 @Override 655 public boolean containsKey(Key key) { 656 return get(key,null)!=null; 657 } 658 659 @Override 660 public String castToString() throws ExpressionException { 661 throw new ExpressionException("Can't cast Complex Object Type Struct to String", 662 "Use Built-In-Function \"serialize(Struct):String\" to create a String from Struct"); 663 } 664 665 @Override 666 public String castToString(String defaultValue) { 667 return defaultValue; 668 } 669 670 @Override 671 public boolean castToBooleanValue() throws ExpressionException { 672 throw new ExpressionException("Can't cast Complex Object Type Struct to a boolean value"); 673 } 674 675 @Override 676 public Boolean castToBoolean(Boolean defaultValue) { 677 return defaultValue; 678 } 679 680 681 @Override 682 public double castToDoubleValue() throws ExpressionException { 683 throw new ExpressionException("Can't cast Complex Object Type Struct to a number value"); 684 } 685 686 @Override 687 public double castToDoubleValue(double defaultValue) { 688 return defaultValue; 689 } 690 691 692 @Override 693 public DateTime castToDateTime() throws ExpressionException { 694 throw new ExpressionException("Can't cast Complex Object Type Struct to a Date"); 695 } 696 697 @Override 698 public DateTime castToDateTime(DateTime defaultValue) { 699 return defaultValue; 700 } 701 702 @Override 703 public int compareTo(boolean b) throws ExpressionException { 704 throw new ExpressionException("can't compare Complex Object Type Struct with a boolean value"); 705 } 706 707 @Override 708 public int compareTo(DateTime dt) throws PageException { 709 throw new ExpressionException("can't compare Complex Object Type Struct with a DateTime Object"); 710 } 711 712 @Override 713 public int compareTo(double d) throws PageException { 714 throw new ExpressionException("can't compare Complex Object Type Struct with a numeric value"); 715 } 716 717 @Override 718 public int compareTo(String str) throws PageException { 719 throw new ExpressionException("can't compare Complex Object Type Struct with a String"); 720 } 721 722 @Override 723 public void setVariableScope(Variables scope) { 724 variable=scope; 725 } 726 727 @Override 728 public int getType() { 729 return SCOPE_UNDEFINED; 730 } 731 732 @Override 733 public String getTypeAsString() { 734 return "undefined"; 735 } 736 737 738 /** 739 * @return the allowImplicidQueryCall 740 */ 741 public boolean isAllowImplicidQueryCall() { 742 return allowImplicidQueryCall; 743 } 744 745 746 /** 747 * @param allowImplicidQueryCall the allowImplicidQueryCall to set 748 */ 749 public boolean setAllowImplicidQueryCall(boolean allowImplicidQueryCall) { 750 boolean old=this.allowImplicidQueryCall; 751 this.allowImplicidQueryCall = allowImplicidQueryCall; 752 return old; 753 } 754 755 /** 756 * @return the checkArguments 757 */ 758 public boolean getCheckArguments() { 759 return checkArguments; 760 } 761 762 @Override 763 public Object call(PageContext pc, Key methodName, Object[] args) throws PageException { 764 Object obj = get(methodName,null); // every none UDF value is fine as default argument 765 if(obj instanceof UDFPlus) { 766 return ((UDFPlus)obj).call(pc,methodName,args,false); 767 } 768 throw new ExpressionException("No matching function ["+methodName+"] found"); 769 } 770 771 @Override 772 public Object callWithNamedValues(PageContext pc, Key methodName, Struct args) throws PageException { 773 Object obj = get(methodName,null); 774 if(obj instanceof UDFPlus) { 775 return ((UDFPlus)obj).callWithNamedValues(pc,methodName,args,false); 776 } 777 throw new ExpressionException("No matching function ["+methodName+"] found"); 778 } 779 780 781 public short getScopeCascadingType() { 782 return type; 783 } 784}