001    package railo.runtime.type.wrap;
002    
003    import java.util.ArrayList;
004    import java.util.Collections;
005    import java.util.Iterator;
006    import java.util.List;
007    import java.util.ListIterator;
008    
009    import railo.runtime.PageContext;
010    import railo.runtime.converter.LazyConverter;
011    import railo.runtime.dump.DumpData;
012    import railo.runtime.dump.DumpProperties;
013    import railo.runtime.dump.DumpUtil;
014    import railo.runtime.exp.ExpressionException;
015    import railo.runtime.exp.PageException;
016    import railo.runtime.op.Caster;
017    import railo.runtime.op.Duplicator;
018    import railo.runtime.type.Array;
019    import railo.runtime.type.ArrayImpl;
020    import railo.runtime.type.Collection;
021    import railo.runtime.type.KeyImpl;
022    import railo.runtime.type.Sizeable;
023    import railo.runtime.type.comparator.NumberComparator;
024    import railo.runtime.type.comparator.TextComparator;
025    import railo.runtime.type.dt.DateTime;
026    import railo.runtime.type.it.KeyIterator;
027    import railo.runtime.type.util.ArrayUtil;
028    
029    /**
030     * 
031     */
032    public class ListAsArray implements Array,List,Sizeable {
033    
034            protected List list;
035            
036            private ListAsArray(List list) {
037                    this.list=list;
038            }
039            
040            public static Array toArray(List list) {
041                    if(list instanceof ArrayAsList) return ((ArrayAsList)list).array;
042                    if(list instanceof Array) return (Array) list;
043                    return new ListAsArray(list);
044            }
045            
046            
047            /**
048             * @see railo.runtime.type.Array#append(java.lang.Object)
049             */
050            public Object append(Object o) throws PageException {
051                    list.add(o);
052                    return o;
053            }
054            
055            
056            /**
057             * @see railo.runtime.type.Array#appendEL(java.lang.Object)
058             */
059            public Object appendEL(Object o) {
060                    list.add(o);
061                    return o;
062            }
063    
064            /**
065             * @see railo.runtime.type.Array#containsKey(int)
066             */
067            public boolean containsKey(int index) {
068                    return get(index-1,null)!=null;
069            }
070    
071            /**
072             * @see railo.runtime.type.Array#get(int, java.lang.Object)
073             */
074            public Object get(int key, Object defaultValue) {
075                    try {
076                            Object rtn = list.get(key-1);
077                            if(rtn==null) return defaultValue;
078                            return rtn;
079                    }
080                    catch(Throwable t) {
081                            return defaultValue;
082                    }
083            }
084    
085            /**
086             * @see railo.runtime.type.Array#getE(int)
087             */
088            public Object getE(int key) throws PageException {
089                    try {
090                            Object rtn = list.get(key-1);
091                            if(rtn==null) throw new ExpressionException("Element at position ["+key+"] does not exist in list");
092                            return rtn;
093                    }
094                    catch(Throwable t) {
095                            throw new ExpressionException("Element at position ["+key+"] does not exist in list",t.getMessage());
096                    }
097            }
098    
099            /**
100             * @see railo.runtime.type.Array#getDimension()
101             */
102            public int getDimension() {
103                    return 1;
104            }
105    
106            public boolean insert(int key, Object value) throws PageException {
107                    try {
108                    list.add(key-1, value);
109                    }
110                    catch(Throwable t) {
111                            throw new ExpressionException("can't insert value to array at position "+key+", array goes from 1 to "+size());
112                    }
113                    return true;
114            }
115    
116            public int[] intKeys() {
117                    ListIterator lit = list.listIterator();
118                    ArrayList keys = new ArrayList();
119                    int index=0;
120                    Object v;
121                    while(lit.hasNext()) {
122                            index=lit.nextIndex()+1;
123                            v=lit.next();
124                            if(v!=null)keys.add(Integer.valueOf(index));
125                    }
126                    int[] intKeys = new int[keys.size()];
127                    Iterator it = keys.iterator();
128                    index=0;
129                    while(it.hasNext()) {
130                            intKeys[index++]=((Integer)it.next()).intValue();
131                    }
132                    
133                    return intKeys;
134            }
135    
136            /**
137             * @see railo.runtime.type.Array#prepend(java.lang.Object)
138             */
139            public Object prepend(Object o) throws PageException {
140                    list.add(0,o);
141                    return o;
142            }
143    
144            public Object removeE(int key) throws PageException {
145                    try {
146                    return list.remove(key-1);
147                    }
148                    catch(Throwable t) {
149                            throw new ExpressionException("can not remove Element at position ["+key+"]",t.getMessage());
150                    }
151            }
152    
153            /**
154             * @see railo.runtime.type.Array#removeEL(int)
155             */
156            public Object removeEL(int key) {
157                    try {
158                            return removeE(key);
159                    } catch (PageException e) {
160                            return null;
161                    }
162            }
163    
164            public void resize(int to) throws PageException {
165                    while(size()<to)list.add(null);
166            }
167    
168            /**
169             * @see railo.runtime.type.Array#setE(int, java.lang.Object)
170             */
171            public Object setE(int key, Object value) throws PageException {
172                    if(key<=size()) {
173                            try {
174                            list.set(key-1, value);
175                            }
176                            catch(Throwable t) {
177                                    throw new ExpressionException("can not set Element at position ["+key+"]",t.getMessage());
178                            }
179                            
180                    }
181                    else {
182                            while(size()<key-1)list.add(null);
183                            list.add(value);
184                    }
185                    return value;
186            }
187    
188            /**
189             * @see railo.runtime.type.Array#setEL(int, java.lang.Object)
190             */
191            public Object setEL(int key, Object value) {
192                    try {
193                            return setE(key, value);
194                    } catch (Throwable t) {}
195                    return value;
196            }
197    
198            public void sort(String sortType, String sortOrder) throws PageException {
199                    if(getDimension()>1)
200                            throw new ExpressionException("only 1 dimensional arrays can be sorted");
201                    
202                    // check sortorder
203                    boolean isAsc=true;
204                    PageException ee=null;
205                    if(sortOrder.equalsIgnoreCase("asc"))isAsc=true;
206                    else if(sortOrder.equalsIgnoreCase("desc"))isAsc=false;
207                    else throw new ExpressionException("invalid sort order type ["+sortOrder+"], sort order types are [asc and desc]");
208                    
209                    // text
210                    if(sortType.equalsIgnoreCase("text")) {
211                            TextComparator comp=new TextComparator(isAsc,false);
212                            Collections.sort(list,comp);
213                            //Arrays.sort(arr,offset,offset+size,comp);
214                            ee=comp.getPageException();
215                    }
216                    // text no case
217                    else if(sortType.equalsIgnoreCase("textnocase")) {
218                            TextComparator comp=new TextComparator(isAsc,true);
219                            Collections.sort(list,comp);
220                            //Arrays.sort(arr,offset,offset+size,comp);
221                            ee=comp.getPageException();
222                    }
223                    // numeric
224                    else if(sortType.equalsIgnoreCase("numeric")) {
225                            NumberComparator comp=new NumberComparator(isAsc);
226                            Collections.sort(list,comp);
227                            //Arrays.sort(arr,offset,offset+size,comp);
228                            ee=comp.getPageException();
229                    }
230                    else {
231                            throw new ExpressionException("invalid sort type ["+sortType+"], sort types are [text, textNoCase, numeric]");
232                    }
233                    if(ee!=null) {
234                            throw new ExpressionException("can only sort arrays with simple values",ee.getMessage());
235                    }
236            }
237    
238            /**
239             * @see railo.runtime.type.Array#toArray()
240             */
241            public Object[] toArray() {
242                    return list.toArray();
243            }
244    
245            /**
246             * @see railo.runtime.type.Array#toArrayList()
247             */
248            public ArrayList toArrayList() {
249                    return new ArrayList(list);
250            }
251    
252            /**
253             * @see railo.runtime.type.Collection#clear()
254             */
255            public void clear() {
256                    list.clear();
257            }
258    
259            /**
260             * @see railo.runtime.type.Collection#containsKey(java.lang.String)
261             */
262            public boolean containsKey(String key) {
263                    return get(key,null)!=null;
264            }
265    
266            /**
267             * @see railo.runtime.type.Collection#containsKey(railo.runtime.type.Collection.Key)
268             */
269            public boolean containsKey(Key key) {
270                    return get(key,null)!=null;
271            }
272    
273            /**
274             * @see railo.runtime.type.Collection#duplicate(boolean)
275             */
276            public Collection duplicate(boolean deepCopy) {new ArrayImpl().duplicate(deepCopy);
277                    return new ListAsArray((List)Duplicator.duplicate(list,deepCopy));
278            }
279    
280            
281    
282            /**
283             * @see railo.runtime.type.Collection#get(java.lang.String)
284             */
285            public Object get(String key) throws PageException {
286                    return getE(Caster.toIntValue(key));
287            }
288    
289            /**
290             * @see railo.runtime.type.Collection#get(railo.runtime.type.Collection.Key)
291             */
292            public Object get(Key key) throws PageException {
293                    return get(key.getString());
294            }
295    
296            /**
297             * @see railo.runtime.type.Collection#get(java.lang.String, java.lang.Object)
298             */
299            public Object get(String key, Object defaultValue) {
300                    double index=Caster.toIntValue(key,Integer.MIN_VALUE);
301                    if(index==Integer.MIN_VALUE) return defaultValue;
302                return get((int)index,defaultValue);
303            }
304    
305            /**
306             * @see railo.runtime.type.Collection#get(railo.runtime.type.Collection.Key, java.lang.Object)
307             */
308            public Object get(Key key, Object defaultValue) {
309                    return get(key.getString(),defaultValue);
310            }
311    
312            /**
313             * @see railo.runtime.type.Collection#keys()
314             */
315            public Key[] keys() {
316                    int[] intKeys = intKeys();
317                    Collection.Key[] keys = new Collection.Key[intKeys.length];
318                    for(int i=0;i<intKeys.length;i++) {
319                            keys[i]=KeyImpl.init(Caster.toString(intKeys[i]));
320                    }
321                    return keys;
322            }
323    
324            /**
325             * @see railo.runtime.type.Collection#keysAsString()
326             */
327            public String[] keysAsString() {
328                    int[] intKeys = intKeys();
329                    String[] keys = new String[intKeys.length];
330                    for(int i=0;i<intKeys.length;i++) {
331                            keys[i]=Caster.toString(intKeys[i]);
332                    }
333                    return keys;
334            }
335    
336            /**
337             *
338             * @see railo.runtime.type.Collection#remove(railo.runtime.type.Collection.Key)
339             */
340            public Object remove(Key key) throws PageException {
341                    return removeE(Caster.toIntValue(key.getString()));
342            }
343    
344            /**
345             * @see railo.runtime.type.Collection#removeEL(java.lang.String)
346             */
347            public Object removeEL(Key key) {
348                    double index=Caster.toIntValue(key.getString(),Integer.MIN_VALUE);
349                    if(index==Integer.MIN_VALUE) return null;
350                return removeEL((int)index);
351            }
352    
353            /**
354             *
355             * @see railo.runtime.type.Collection#set(java.lang.String, java.lang.Object)
356             */
357            public Object set(String key, Object value) throws PageException {
358                    return setE(Caster.toIntValue(key),value);
359            }
360    
361            /**
362             *
363             * @see railo.runtime.type.Collection#set(railo.runtime.type.Collection.Key, java.lang.Object)
364             */
365            public Object set(Key key, Object value) throws PageException {
366                    return set(key.getString(),value);
367            }
368    
369            /**
370             * @see railo.runtime.type.Collection#setEL(java.lang.String, java.lang.Object)
371             */
372            public Object setEL(String key, Object value) {
373                    double index=Caster.toIntValue(key,Integer.MIN_VALUE);
374                    if(index==Integer.MIN_VALUE) return value;
375                return setEL((int)index,value);
376            }
377    
378            /**
379             * @see railo.runtime.type.Collection#setEL(railo.runtime.type.Collection.Key, java.lang.Object)
380             */
381            public Object setEL(Key key, Object value) {
382                    return setEL(key.getString(), value);
383            }
384    
385            /**
386             * @see railo.runtime.type.Collection#size()
387             */
388            public int size() {
389                    return list.size();
390            }
391    
392            public DumpData toDumpData(PageContext pageContext, int maxlevel, DumpProperties dp) {
393                    return DumpUtil.toDumpData(list, pageContext,maxlevel,dp);
394            }
395    
396            /**
397             * @see railo.runtime.type.Iteratorable#iterator()
398             */
399            public Iterator iterator() {
400                    return list.iterator();
401            }
402    
403            /**
404             * @see railo.runtime.type.Iteratorable#keyIterator()
405             */
406            public Iterator keyIterator() {
407                    return new KeyIterator(keys());
408            }
409    
410            /**
411         * @see railo.runtime.op.Castable#castToString()
412         */
413        public String castToString() throws PageException {
414            throw new ExpressionException("Can't cast Complex Object Type "+Caster.toClassName(list)+" to String",
415              "Use Build-In-Function \"serialize(Array):String\" to create a String from Array");
416        }
417    
418            /**
419             * @see railo.runtime.op.Castable#castToString(java.lang.String)
420             */
421            public String castToString(String defaultValue) {
422                    return defaultValue;
423            }
424    
425    
426        /**
427         * @see railo.runtime.op.Castable#castToBooleanValue()
428         */
429        public boolean castToBooleanValue() throws PageException {
430            throw new ExpressionException("Can't cast Complex Object Type "+Caster.toClassName(list)+" to a boolean value");
431        }
432        
433        /**
434         * @see railo.runtime.op.Castable#castToBoolean(java.lang.Boolean)
435         */
436        public Boolean castToBoolean(Boolean defaultValue) {
437            return defaultValue;
438        }
439    
440    
441        /**
442         * @see railo.runtime.op.Castable#castToDoubleValue()
443         */
444        public double castToDoubleValue() throws PageException {
445            throw new ExpressionException("Can't cast Complex Object Type "+Caster.toClassName(list)+" to a number value");
446        }
447        
448        /**
449         * @see railo.runtime.op.Castable#castToDoubleValue(double)
450         */
451        public double castToDoubleValue(double defaultValue) {
452            return defaultValue;
453        }
454    
455    
456        /**
457         * @see railo.runtime.op.Castable#castToDateTime()
458         */
459        public DateTime castToDateTime() throws PageException {
460            throw new ExpressionException("Can't cast Complex Object Type "+Caster.toClassName(list)+" to a Date");
461        }
462        
463        /**
464         * @see railo.runtime.op.Castable#castToDateTime(railo.runtime.type.dt.DateTime)
465         */
466        public DateTime castToDateTime(DateTime defaultValue) {
467            return defaultValue;
468        }
469    
470            /**
471             * @see railo.runtime.op.Castable#compare(boolean)
472             */
473            public int compareTo(boolean b) throws PageException {
474                    throw new ExpressionException("can't compare Complex Object Type "+Caster.toClassName(list)+" with a boolean value");
475            }
476    
477            /**
478             * @see railo.runtime.op.Castable#compareTo(railo.runtime.type.dt.DateTime)
479             */
480            public int compareTo(DateTime dt) throws PageException {
481                    throw new ExpressionException("can't compare Complex Object Type "+Caster.toClassName(list)+" with a DateTime Object");
482            }
483    
484            /**
485             * @see railo.runtime.op.Castable#compareTo(double)
486             */
487            public int compareTo(double d) throws PageException {
488                    throw new ExpressionException("can't compare Complex Object Type "+Caster.toClassName(list)+" with a numeric value");
489            }
490    
491            /**
492             * @see railo.runtime.op.Castable#compareTo(java.lang.String)
493             */
494            public int compareTo(String str) throws PageException {
495                    throw new ExpressionException("can't compare Complex Object Type "+Caster.toClassName(list)+" with a String");
496            }
497    
498            /**
499             *
500             * @see java.lang.Object#toString()
501             */
502            public String toString() {
503                    return LazyConverter.serialize(this);
504            }
505            
506            /**
507             * @see java.lang.Object#clone()
508             */
509            public Object clone() {
510                    return duplicate(true);
511            }
512    
513            /**
514             * @see java.util.List#addEntry(E)
515             */
516            public boolean add(Object o) {
517                    return list.add(o);
518            }
519    
520            /**
521             * @see java.util.List#add(int, E)
522             */
523            public void add(int index, Object element) {
524                    list.add(index, element);
525            }
526    
527            /**
528             * @see java.util.List#addAll(java.util.Collection)
529             */
530            public boolean addAll(java.util.Collection c) {
531                    return list.addAll(c);
532            }
533    
534            /**
535             * @see java.util.List#addAll(int, java.util.Collection)
536             */
537            public boolean addAll(int index, java.util.Collection c) {
538                    return list.addAll(index, c);
539            }
540    
541            /**
542             * @see java.util.List#contains(java.lang.Object)
543             */
544            public boolean contains(Object o) {
545                    return list.contains(o);
546            }
547    
548            /**
549             * @see java.util.List#containsAll(java.util.Collection)
550             */
551            public boolean containsAll(java.util.Collection c) {
552                    return list.contains(c);
553            }
554    
555            /**
556             * @see java.util.List#get(int)
557             */
558            public Object get(int index) {
559                    return list.get(index);
560            }
561    
562            /**
563             * @see java.util.List#indexOf(java.lang.Object)
564             */
565            public int indexOf(Object o) {
566                    return list.indexOf(o);
567            }
568    
569            /**
570             * @see java.util.List#isEmpty()
571             */
572            public boolean isEmpty() {
573                    return list.isEmpty();
574            }
575    
576            /**
577             * @see java.util.List#lastIndexOf(java.lang.Object)
578             */
579            public int lastIndexOf(Object o) {
580                    return list.lastIndexOf(o);
581            }
582    
583            /**
584             * @see java.util.List#listIterator()
585             */
586            public ListIterator listIterator() {
587                    return list.listIterator();
588            }
589    
590            /**
591             * @see java.util.List#listIterator(int)
592             */
593            public ListIterator listIterator(int index) {
594                    return list.listIterator(index);
595            }
596    
597            /**
598             * @see java.util.List#remove(java.lang.Object)
599             */
600            public boolean remove(Object o) {
601                    return list.remove(o);
602            }
603    
604            /**
605             * @see java.util.List#remove(int)
606             */
607            public Object remove(int index) {
608                    return list.remove(index);
609            }
610    
611            /**
612             * @see java.util.List#removeAll(java.util.Collection)
613             */
614            public boolean removeAll(java.util.Collection c) {
615                    return list.removeAll(c);
616            }
617    
618            /**
619             * @see java.util.List#retainAll(java.util.Collection)
620             */
621            public boolean retainAll(java.util.Collection c) {
622                    return list.retainAll(c);
623            }
624    
625            /**
626             * @see java.util.List#set(int, E)
627             */
628            public Object set(int index, Object element) {
629                    return list.set(index, element);
630            }
631    
632            /**
633             * @see java.util.List#subList(int, int)
634             */
635            public List subList(int fromIndex, int toIndex) {
636                    return list.subList(fromIndex, toIndex);
637            }
638    
639            /**
640             * @see java.util.List#toArray(T[])
641             */
642            public Object[] toArray(Object[] a) {
643                    return list.toArray(a);
644            }
645    
646    
647            /**
648             * @see railo.runtime.type.Array#toList()
649             */
650            public List toList() {
651                    return this;
652            }
653    
654            public Iterator valueIterator() {
655                    return list.iterator();
656            }
657    
658            /**
659             * @see railo.runtime.type.Sizeable#sizeOf()
660             */
661            public long sizeOf() {
662                    return ArrayUtil.sizeOf(list);
663            }
664    }