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