001    package railo.runtime.type.scope;
002    
003    import java.util.ArrayList;
004    import java.util.Comparator;
005    import java.util.Iterator;
006    import java.util.LinkedHashMap;
007    import java.util.List;
008    import java.util.Map;
009    import java.util.Set;
010    
011    import railo.print;
012    import railo.commons.lang.CFTypes;
013    import railo.runtime.PageContext;
014    import railo.runtime.config.NullSupportHelper;
015    import railo.runtime.dump.DumpData;
016    import railo.runtime.dump.DumpProperties;
017    import railo.runtime.dump.DumpTable;
018    import railo.runtime.dump.DumpUtil;
019    import railo.runtime.dump.SimpleDumpData;
020    import railo.runtime.exp.ExpressionException;
021    import railo.runtime.exp.PageException;
022    import railo.runtime.op.Caster;
023    import railo.runtime.op.Decision;
024    import railo.runtime.type.Array;
025    import railo.runtime.type.ArrayImpl;
026    import railo.runtime.type.Collection;
027    import railo.runtime.type.KeyImpl;
028    import railo.runtime.type.Null;
029    import railo.runtime.type.Struct;
030    import railo.runtime.type.StructImpl;
031    import railo.runtime.type.UDF;
032    import railo.runtime.type.util.CollectionUtil;
033    import railo.runtime.type.util.MemberUtil;
034    import railo.runtime.type.wrap.ArrayAsList;
035    
036    /**
037     * implementation of the argument scope 
038     */
039    public final class ArgumentImpl extends ScopeSupport implements Argument {
040                    
041            private boolean bind;
042            private Set functionArgumentNames;
043            //private boolean supportFunctionArguments; 
044            
045            /**
046             * constructor of the class
047             */
048            public ArgumentImpl() {
049                    super("arguments",SCOPE_ARGUMENTS,Struct.TYPE_LINKED);
050                    //this(true);
051            }
052    
053    
054            @Override
055            public void release() {
056                    release(null);
057            }
058            
059            @Override
060            public void release(PageContext pc) {
061                    functionArgumentNames=null;
062                    if(pc==null)super.release();
063                    else super.release(pc);
064            }
065            
066            
067            
068         @Override 
069        public void setBind(boolean bind) { 
070                this.bind=bind; 
071        }       
072        
073        @Override 
074        public boolean isBind() { 
075            return this.bind; 
076        } 
077        
078        public Object getFunctionArgument(String key, Object defaultValue) {
079                    return getFunctionArgument(KeyImpl.getInstance(key), defaultValue);
080            }
081    
082            public Object getFunctionArgument(Collection.Key key, Object defaultValue) {
083                    return super.get(key,defaultValue);
084            }
085            
086    
087            @Override
088            public boolean containsFunctionArgumentKey(Key key) {
089                    return super.containsKey(key);//functionArgumentNames!=null && functionArgumentNames.contains(key);
090            }
091            
092            
093            
094            @Override
095            public Object get(Collection.Key key, Object defaultValue) {
096                    /*if(NullSupportHelper.full()) {
097                            Object o=super.get(key,NullSupportHelper.NULL());
098                            if(o!=NullSupportHelper.NULL())return o;
099                            
100                            o=get(Caster.toIntValue(key.getString(),-1),NullSupportHelper.NULL());
101                            if(o!=NullSupportHelper.NULL())return o;
102                            return defaultValue;
103                    }*/
104                    
105                    Object o=super.g(key,Null.NULL);
106                    if(o!=Null.NULL)return o;
107    
108                    o=get(Caster.toIntValue(key.getString(),-1),Null.NULL);
109                    if(o!=Null.NULL)return o;
110                    return defaultValue;
111            }
112            
113            
114    
115            @Override
116            public Object get(Collection.Key key) throws ExpressionException {
117                    /*if(NullSupportHelper.full()) {
118                            Object o=super.get(key,NullSupportHelper.NULL());
119                            if(o!=NullSupportHelper.NULL())return o;
120            
121                            o=get(Caster.toIntValue(key.getString(),-1),NullSupportHelper.NULL());
122                            if(o!=NullSupportHelper.NULL())return o;
123                            throw new ExpressionException("key ["+key.getString()+"] doesn't exist in argument scope. existing keys are ["+
124                                            railo.runtime.type.List.arrayToList(CollectionUtil.keys(this),", ")
125                                            +"]");
126                    }*/
127                    
128                    // null is supported as returned value with argument scope
129                    Object o=super.g(key,Null.NULL);
130                    if(o!=Null.NULL)return o;
131    
132                    o=get(Caster.toIntValue(key.getString(),-1),Null.NULL);
133                    if(o!=Null.NULL)return o;
134                    
135                    throw new ExpressionException("key ["+key.getString()+"] doesn't exist in argument scope. existing keys are ["+
136                                    railo.runtime.type.util.ListUtil.arrayToList(CollectionUtil.keys(this),", ")
137                                    +"]");
138            }
139            
140            
141    
142            @Override
143            public Object get(int intKey, Object defaultValue) {
144                    Iterator<Object> it = valueIterator(); //keyIterator();//getMap().keySet().iterator();
145                    int count=0;
146                    Object o;
147                    while(it.hasNext()) {
148                            o=it.next();
149                            if((++count)==intKey) {
150                                    return o;//super.get(o.toString(),defaultValue);
151                            }
152                    }
153                    return defaultValue;
154            }
155    
156            /**
157             * return a value matching to key
158             * @param intKey
159             * @return value matching key
160             * @throws PageException
161             */
162            public Object getE(int intKey) throws PageException {
163                    Iterator it = valueIterator();//getMap().keySet().iterator();
164                    int count=0;
165                    Object o;
166                    while(it.hasNext()) {
167                            o=it.next();
168                            if((++count)==intKey) {
169                                    return o;//super.get(o.toString());
170                            }
171                    }
172                    throw new ExpressionException("invalid index ["+intKey+"] for argument scope"); 
173            }
174            
175            @Override
176            public DumpData toDumpData(PageContext pageContext, int maxlevel, DumpProperties dp) {
177                    DumpTable htmlBox = new DumpTable("struct","#9999ff","#ccccff","#000000");
178                    htmlBox.setTitle("Scope Arguments");
179                    if(size()>10 && dp.getMetainfo())htmlBox.setComment("Entries:"+size());
180                
181                    maxlevel--;
182                    //Map mapx=getMap();
183                    Iterator<Key> it = keyIterator();//mapx.keySet().iterator();
184                    int count=0;
185                    Collection.Key key;
186                    int maxkeys=dp.getMaxKeys();
187                    int index=0;
188                    while(it.hasNext()) {
189                            key=it.next();//it.next();
190                            
191                            if(DumpUtil.keyValid(dp, maxlevel,key)){
192                                    if(maxkeys<=index++)break;
193                                    htmlBox.appendRow(3,
194                                                    new SimpleDumpData(key.getString()),
195                                                    new SimpleDumpData(++count),
196                                                    DumpUtil.toDumpData(get(key,null), 
197                                                    pageContext,maxlevel,dp));
198                            }
199                    }
200                    return htmlBox;
201            }
202    
203    
204            @Override
205            public int getDimension() {
206                    return 1;
207            }
208    
209            @Override
210            public Object setEL(int intKey, Object value) {
211                    int count=0;
212                    
213                    if(intKey>size()) {
214                            return setEL(Caster.toString(intKey),value);
215                    }
216                    //Iterator it = keyIterator();
217                    Key[] keys = keys();
218                    for(int i=0;i<keys.length;i++) {
219                            if((++count)==intKey) {
220                                    return super.setEL(keys[i],value);
221                            }
222                    }
223                    return value;
224            }
225    
226    
227            @Override
228            public Object setE(int intKey, Object value) throws PageException {
229    
230                    if(intKey>size()) {
231                            return set(Caster.toString(intKey),value);
232                    }
233                    //Iterator it = keyIterator();
234                    Key[] keys = keys();
235                    for(int i=0;i<keys.length;i++) {
236                            if((i+1)==intKey) {
237                                    return super.set(keys[i],value);
238                            }
239                    }
240                    throw new ExpressionException("invalid index ["+intKey+"] for argument scope"); 
241            }
242    
243    
244            @Override
245            public int[] intKeys() {
246                    int[] ints=new int[size()];
247                    for(int i=0;i<ints.length;i++)ints[i]=i+1;
248                    return ints;
249            }
250    
251    
252            @Override
253            public boolean insert(int index, Object value) throws ExpressionException {
254                    return insert(index, ""+index, value);
255            }
256            
257            @Override
258            public boolean insert(int index, String key, Object value) throws ExpressionException {
259                    int len=size();
260                    if(index<1 || index>len)
261                            throw new ExpressionException("invalid index to insert a value to argument scope",len==0?"can't insert in a empty argument scope":"valid index goes from 1 to "+(len-1));
262                    
263                    // remove all upper
264                            LinkedHashMap lhm = new LinkedHashMap();
265                            Collection.Key[] keys=keys();
266                            
267                            Collection.Key k;
268                            for(int i=1;i<=keys.length;i++) {
269                                    if(i<index)continue;
270                                    k=keys[i-1];
271                                    lhm.put(k.getString(),get(k,null));
272                                    removeEL(k);
273                            }
274                    
275                    // set new value
276                            setEL(key,value);
277                    
278                    // reset upper values
279                            Iterator it = lhm.entrySet().iterator();
280                            Map.Entry entry;
281                            while(it.hasNext()) {                   
282                                    entry=(Entry) it.next();
283                                    setEL(KeyImpl.toKey(entry.getKey()),entry.getValue());
284                            }               
285                    return true;
286            }
287    
288    
289            @Override
290            public Object append(Object o) throws PageException {
291                    return set(Caster.toString(size()+1),o);
292            }
293            
294            @Override
295            public Object appendEL(Object o) {
296                    try {
297                            return append(o);
298                    } catch (PageException e) {
299                            return null;
300                    }
301            }
302    
303    
304            @Override
305            public Object prepend(Object o) throws PageException {
306                    for(int i=size();i>0;i--) {
307                            setE(i+1,getE(i));
308                    }
309                    setE(1,o);
310                    return o;
311            }
312    
313    
314            @Override
315            public void resize(int to) throws PageException {
316                    for(int i=size(); i<to; i++) {
317                            append(null);
318                    }
319                    //throw new ExpressionException("can't resize this array");
320            }
321    
322    
323    
324            @Override
325            public void sort(String sortType, String sortOrder) throws ExpressionException {
326                    // TODO Impl.
327                    throw new ExpressionException("can't sort ["+sortType+"-"+sortOrder+"] Argument Scope","not Implemnted Yet");
328            }
329    
330            public void sort(Comparator com) throws ExpressionException {
331                    // TODO Impl.
332                    throw new ExpressionException("can't sort Argument Scope","not Implemnted Yet");
333            }
334    
335            @Override
336            public Object[] toArray() {
337                    Iterator it = keyIterator();//getMap().keySet().iterator();
338                    Object[] arr=new Object[size()];
339                    int count=0;
340                    
341                    while(it.hasNext()) {
342                            arr[count++]=it.next();
343                    }
344                    return arr;
345            }
346            
347            public Object setArgument(Object obj) throws PageException {
348                    if(obj==this) return obj;
349                    
350                    
351                    if(Decision.isStruct(obj)) {
352                            clear(); // TODO bessere impl. anstelle vererbung wrao auf struct
353                            Struct sct=Caster.toStruct(obj);
354                            Iterator<Key> it = sct.keyIterator();
355                            Key key;
356                            while(it.hasNext()) {
357                                    key=it.next();
358                                    setEL(key, sct.get(key,null));
359                            }
360                            return obj;
361                    }
362                    throw new ExpressionException("can not overwrite arguments scope");
363            }
364    
365    
366            public ArrayList toArrayList() {
367                    ArrayList list = new ArrayList();
368                    Object[] arr = toArray();
369                    for(int i=0;i<arr.length;i++) {
370                            list.add(arr[i]);
371                    }
372                    return list;
373            }
374    
375            @Override
376            public Object removeE(int intKey) throws PageException {
377                    Key[] keys = keys();
378                    for(int i=0;i<keys.length;i++) {
379                            if((i+1)==intKey) {
380                                    return super.remove(keys[i]);
381                            }
382                    }
383                    throw new ExpressionException("can't remove argument number ["+intKey+"], argument doesn't exist");
384            }
385    
386            @Override
387            public Object removeEL(int intKey) {
388                    Key[] keys = keys();
389                    for(int i=0;i<keys.length;i++) {
390                            if((i+1)==intKey) {
391                                    return super.removeEL (keys[i]);
392                            }
393                    }
394                    return null;
395            }
396    
397        @Override
398        public boolean containsKey(Collection.Key key) {
399            if(NullSupportHelper.full()) return super.containsKey(key);
400            
401                    return super.g(key,null)!=null;
402            // return get(key,NullSupportHelper.NULL())!=NullSupportHelper.NULL() && super.containsKey(key);
403        }
404        /*
405        public boolean containsKey(Collection.Key key) {
406            return get(key,null)!=null && super.containsKey(key);
407        }*/
408    
409        @Override
410        public boolean containsKey(int key) {
411            return key>0 && key<=size();
412        }
413    
414            @Override
415            public List toList() {
416                    return ArrayAsList.toList(this);
417            }
418            
419    
420            @Override
421            public Collection duplicate(boolean deepCopy) {
422                    ArgumentImpl trg=new ArgumentImpl();
423                    trg.bind=false;
424                    trg.functionArgumentNames=functionArgumentNames;
425                    //trg.supportFunctionArguments=supportFunctionArguments;
426                    copy(this,trg,deepCopy);
427                    return trg;
428            }
429    
430            public void setFunctionArgumentNames(Set functionArgumentNames) {// future add to interface
431                    this.functionArgumentNames=functionArgumentNames;
432            }
433    /*
434            public void setNamedArguments(boolean namedArguments) {
435                    this.namedArguments=namedArguments;
436            }
437            public boolean isNamedArguments() {
438                    return namedArguments;
439            }
440    */
441    
442            /**
443             * converts a argument scope to a regular struct
444             * @param arg argument scope to convert
445             * @return resulting struct
446             */
447            public static Struct toStruct(Argument arg) {
448                    Struct trg=new StructImpl();
449                    StructImpl.copy(arg, trg, false);
450                    return trg;
451            }
452    
453            /**
454             * converts a argument scope to a regular array
455             * @param arg argument scope to convert
456             * @return resulting array
457             */
458            public static Array toArray(Argument arg) {
459                    ArrayImpl trg=new ArrayImpl();
460                    int[] keys = arg.intKeys();
461                    for(int i=0;i<keys.length;i++){
462                            trg.setEL(keys[i],
463                                            arg.get(keys[i],null));
464                    }
465                    return trg;
466            }
467    
468            @Override
469            public Object get(PageContext pc, Key key, Object defaultValue) {
470                    return get(key, defaultValue);
471            }
472    
473            @Override
474            public Object get(PageContext pc, Key key) throws PageException {
475                    return get(key);
476            }
477    
478            @Override
479            public Object set(PageContext pc, Key propertyName, Object value) throws PageException {
480                    return set(propertyName, value);
481            }
482    
483            @Override
484            public Object setEL(PageContext pc, Key propertyName, Object value) {
485                    return setEL(propertyName, value);
486            }
487    
488            @Override
489            public Object call(PageContext pc, Key methodName, Object[] args) throws PageException {
490                    Object obj = get(methodName,null);
491                    if(obj instanceof UDF) {
492                            return ((UDF)obj).call(pc,args,false);
493                    }
494                    return MemberUtil.call(pc, this, methodName, args, CFTypes.TYPE_ARRAY, "array");
495            }
496    
497            @Override
498            public Object callWithNamedValues(PageContext pc, Key methodName, Struct args) throws PageException {
499                    Object obj = get(methodName,null);
500                    if(obj instanceof UDF) {
501                            return ((UDF)obj).callWithNamedValues(pc,args,false);
502                    }
503                    return MemberUtil.callWithNamedValues(pc,this,methodName,args, CFTypes.TYPE_ARRAY, "array");
504            }
505    }