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}