001    package railo.runtime.type;
002    
003    import java.util.ArrayList;
004    import java.util.Date;
005    import java.util.Iterator;
006    import java.util.List;
007    
008    import railo.commons.lang.SizeOf;
009    import railo.runtime.PageContext;
010    import railo.runtime.dump.DumpData;
011    import railo.runtime.dump.DumpProperties;
012    import railo.runtime.dump.DumpUtil;
013    import railo.runtime.engine.ThreadLocalPageContext;
014    import railo.runtime.exp.DatabaseException;
015    import railo.runtime.exp.ExpressionException;
016    import railo.runtime.exp.PageException;
017    import railo.runtime.exp.PageRuntimeException;
018    import railo.runtime.op.Caster;
019    import railo.runtime.op.Duplicator;
020    import railo.runtime.op.Operator;
021    import railo.runtime.op.ThreadLocalDuplication;
022    import railo.runtime.op.date.DateCaster;
023    import railo.runtime.reflection.Reflector;
024    import railo.runtime.reflection.pairs.MethodInstance;
025    import railo.runtime.type.dt.DateTime;
026    import railo.runtime.type.it.KeyIterator;
027    import railo.runtime.type.scope.UndefinedImpl;
028    import railo.runtime.type.util.CollectionUtil;
029    import railo.runtime.util.ArrayIterator;
030    
031    /**
032     * implementation of the query column
033     */
034    public class QueryColumnImpl implements QueryColumnPro,Sizeable,Objects {
035    
036        private static final int CAPACITY=32;
037        
038            protected int type;
039            protected int size;
040            protected Object[] data;
041        
042        protected boolean typeChecked=false;
043        protected QueryImpl query;
044        protected Collection.Key key;
045    
046            /**
047             * constructor with type
048             * @param query
049             * @param key 
050             * @param type
051             */
052        public QueryColumnImpl(QueryImpl query, Collection.Key key, int type) {
053                    this.data=new Object[CAPACITY];
054                    this.type=type;
055            this.key=key;
056            this.query=query;
057            }
058    
059            /**
060             * constructor with array
061             * @param query
062             * @param array
063             * @param type
064             */
065        public QueryColumnImpl(QueryImpl query, Collection.Key key, Array array,int type) {
066                    data=array.toArray();
067                size=array.size();
068                    this.type=type;
069                    this.query=query;
070                    this.key=key;
071            }
072    
073            /**
074             * @param query
075             * @param type type as (java.sql.Types.XYZ) int
076             * @param size 
077             */
078        public QueryColumnImpl(QueryImpl query, Collection.Key key, int type, int size) {
079                    this.data=new Object[size];
080                    this.type=type;
081                    this.size=size;
082                    this.query=query;
083                    this.key=key;
084            }
085            
086    
087            /**
088             * Constructor of the class
089             * for internal usage only
090             */
091            public QueryColumnImpl() {
092            }
093    
094            /**
095             * @see railo.runtime.type.Collection#size()
096             */
097            public int size() {
098                    return size;
099            }
100    
101            /**
102             * @see railo.runtime.type.Collection#keysAsString()
103             */
104            public String[] keysAsString() {
105                String[] k=new String[size()];
106            int len=k.length;
107                    for(int i=1;i<=len;i++) {
108                            k[i-1]=Caster.toString(i);
109                    }
110                    return k;
111            }
112    
113            public Collection.Key[] keys() {
114                    Collection.Key[] k=new Collection.Key[size()];
115            int len=k.length;
116                    for(int i=1;i<=len;i++) {
117                            k[i-1]=KeyImpl.init(Caster.toString(i));
118                    }
119                    return k;
120            }
121    
122            /**
123             * @see railo.runtime.type.Collection#remove(railo.runtime.type.Collection.Key)
124             */
125            public Object remove(Collection.Key key) throws PageException {
126                    resetType();
127                    return set(Caster.toIntValue(key.getString()),"");
128            }
129    
130            /**
131             * @see railo.runtime.type.QueryColumn#remove(int)
132             */
133            public Object remove(int row) throws DatabaseException {
134            // query.disconnectCache();
135            resetType();
136                    return set(row,"");
137            }
138            
139    
140            /**
141             *
142             * @see railo.runtime.type.Collection#removeEL(railo.runtime.type.Collection.Key)
143             */
144            public Object removeEL(Collection.Key key) {
145            // query.disconnectCache();
146            resetType();
147                    return setEL(Caster.toIntValue(key.getString(),-1),"");
148            }
149    
150            /**
151             * @see railo.runtime.type.QueryColumn#removeEL(int)
152             */
153            public Object removeEL(int row) {
154            // query.disconnectCache();
155            resetType();
156                    return setEL(row,"");
157            }
158    
159            /**
160             * @see railo.runtime.type.Collection#clear()
161             */
162            public synchronized void clear() {
163            // query.disconnectCache();
164            resetType();
165                    data=new Object[CAPACITY];
166                    size=0;
167            }
168            
169            /**
170             * @see railo.runtime.type.ref.Reference#remove(PageContext pc)
171             */
172            public Object remove(PageContext pc) throws PageException {
173            return remove(query.getCurrentrow());
174            }
175    
176            public Object removeEL(PageContext pc) {
177            return removeEL(query.getCurrentrow());
178            }
179            
180            /**
181             * @throws PageException
182             * @see railo.runtime.type.Collection#get(java.lang.String)
183             */
184            public Object get(String key) throws PageException {
185            int row=Caster.toIntValue(key,Integer.MIN_VALUE);
186                if(row==Integer.MIN_VALUE) {
187                Object rtn = getChildElement(key, null);
188                if(rtn!=null) return rtn;
189                    //QueryColumn cc=query.getColumn(key,null);
190                //if(cc!=null) return cc;
191                throw new DatabaseException("key ["+key+"] not found",null,null,null);
192            }
193                return get(row);
194            }
195    
196            /**
197             * @see railo.runtime.type.Collection#get(railo.runtime.type.Collection.Key)
198             */
199            public Object get(Collection.Key key) throws PageException {
200                    int row=Caster.toIntValue(key.getString(),Integer.MIN_VALUE);
201                    if(row==Integer.MIN_VALUE) {
202                            Object child=getChildElement(key,null);
203                    if(child!=null) return child;
204                throw new DatabaseException("key ["+key+"] not found",null,null,null);
205            }
206                return get(row);
207            }
208            
209            
210            
211    
212        private Object getChildElement(Key key, Object defaultValue) {
213            // column and query has same name
214            if(key.equals(this.key)) {
215                    return query.get(key,defaultValue);
216            }
217            // get it from undefined scope
218                    PageContext pc = ThreadLocalPageContext.get();
219                    if(pc!=null){
220                            UndefinedImpl undefined = ((UndefinedImpl)pc.undefinedScope());
221                            boolean old = undefined.setAllowImplicidQueryCall(false);
222                            Object sister = undefined.get(this.key,null);
223                            undefined.setAllowImplicidQueryCall(old);
224                            if(sister!=null){
225                                    try {
226                                            return pc.get(sister, key);
227                                    } catch (PageException e) {
228                                            return defaultValue;
229                                    }
230                            }
231                    }
232            return defaultValue;
233            }
234        
235        private Object getChildElement(String key, Object defaultValue) {
236            // column and query has same name
237            if(key.equalsIgnoreCase(this.key.getString())) {
238                    return query.get(key,defaultValue);
239            }
240            // get it from undefined scope
241                    PageContext pc = ThreadLocalPageContext.get();
242                    if(pc!=null){
243                            UndefinedImpl undefined = ((UndefinedImpl)pc.undefinedScope());
244                            boolean old = undefined.setAllowImplicidQueryCall(false);
245                            Object sister = undefined.get(this.key,null);
246                            undefined.setAllowImplicidQueryCall(old);
247                            if(sister!=null)return pc.get(sister, key,defaultValue);
248                    }
249            return defaultValue;
250            }
251    
252            /**
253         * @see railo.runtime.type.ContextCollection#get(railo.runtime.PageContext, java.lang.String)
254         */
255        public Object get(PageContext pc, String key) throws PageException {
256            int row=Caster.toIntValue(key,Integer.MIN_VALUE);
257            if(row==Integer.MIN_VALUE) {
258                Object rtn=getChildElement(key, null);
259                //Object rtn=pc.get(get(query.getCurrentrow(),null),key,null);
260                //if(rtn!=null) return rtn;
261                //rtn= query.get(key,null);
262                if(rtn!=null) return rtn;
263                throw new ExpressionException("query column has no key with name ["+key+"]");
264            }
265            return get(row);
266        }
267    
268        /**
269         * @see railo.runtime.type.QueryColumn#get(int)
270         */
271        public Object get(int row){
272            if(row<1 || row>size) return "";
273            Object o=data[row-1];
274            return o==null?"":o;
275        }
276    
277        /**
278         * touch the given line on the column at given row
279         * @param row
280         * @return new row or existing
281         * @throws DatabaseException
282         */
283        public Object touch(int row) throws DatabaseException{
284            // query.disconnectCache();
285            if(row<1 || row>size) return "";
286            Object o=data[row-1];
287            if(o!=null) return o;
288            return set(row,new StructImpl());
289        }
290        
291        /**
292         * touch the given line on the column at given row
293         * @param row
294         * @return new row or existing
295         * @throws DatabaseException
296         */
297        public Object touchEL(int row) {
298            // query.disconnectCache();
299            if(row<1 || row>size) return "";
300            Object o=data[row-1];
301            if(o!=null) return o;
302            return setEL(row,new StructImpl());
303        }
304    
305            /**
306             * @see railo.runtime.type.Collection#get(railo.runtime.type.Collection.Key, java.lang.Object)
307             */
308            public Object get(Collection.Key key, Object defaultValue) {
309                int row=Caster.toIntValue(key.getString(),Integer.MIN_VALUE);
310                if(row==Integer.MIN_VALUE) {
311                    return getChildElement(key, defaultValue);
312                    //Object rtn= query.getColumn(key,null);
313                    //if(rtn!=null)return rtn;
314                    //return defaultValue;
315                }
316                return get(row,defaultValue);
317            }
318    
319            /**
320             *
321             * @see railo.runtime.type.Collection#get(java.lang.String, java.lang.Object)
322             */
323            public Object get(String key, Object defaultValue) {
324                int row=Caster.toIntValue(key,Integer.MIN_VALUE);
325                if(row==Integer.MIN_VALUE) {
326                    return getChildElement(key, defaultValue);
327                    //Object rtn= query.getColumn(key,null);
328                    //if(rtn!=null)return rtn;
329                    //return defaultValue;
330                }
331                return get(row,defaultValue);
332            }
333    
334        /**
335         * @param pc
336         * @param key
337         * @param defaultValue
338         * @return
339         */
340        public Object get(PageContext pc, String key, Object defaultValue) {
341            int row=Caster.toIntValue(key,Integer.MIN_VALUE);
342            if(row==Integer.MIN_VALUE) {
343                return getChildElement(key, defaultValue);
344            }
345            return get(row,defaultValue);
346        }
347    
348            /**
349             * @see railo.runtime.type.QueryColumn#get(int, java.lang.Object)
350             */
351            public Object get(int row, Object defaultValue) {
352                if(row<1 || row>size) return defaultValue;
353                Object o=data[row-1];
354                return o==null?defaultValue:o;
355            }
356    
357            /**
358             * @see railo.runtime.type.Collection#set(java.lang.String, java.lang.Object)
359             */
360            public Object set(String key, Object value) throws PageException {
361                int row=Caster.toIntValue(key,Integer.MIN_VALUE);
362                if(row==Integer.MIN_VALUE)return query.set(key,value);
363                return set(row,value);
364            }
365    
366            public Object set(Collection.Key key, Object value) throws PageException {
367                int row=Caster.toIntValue(key.getString(),Integer.MIN_VALUE);
368                if(row==Integer.MIN_VALUE)return query.set(key,value);
369                return set(row,value);
370            }
371    
372        /**
373             * @see railo.runtime.type.QueryColumn#set(int, java.lang.Object)
374             */
375            public synchronized Object set(int row, Object value) throws DatabaseException {
376            // query.disconnectCache();
377            if(row<1) throw new DatabaseException("invalid row number ["+row+"]","valid row numbers a greater or equal to one",null,null,null);
378                if(row>size) {
379                    if(size==0)throw new DatabaseException("cannot set a value to a empty query, you first have to add a row",null,null,null,null);
380                    throw new DatabaseException("invalid row number ["+row+"]","valid row numbers goes from 1 to "+size,null,null,null);
381                }
382                
383                value=reDefineType(value);
384                data[row-1]=value;
385                return value;
386            }
387            /**
388             * @see railo.runtime.type.Collection#setEL(java.lang.String, java.lang.Object)
389             */
390            public synchronized Object setEL(String key, Object value) {
391                int index=Caster.toIntValue(key,Integer.MIN_VALUE);
392                    if(index==Integer.MIN_VALUE) query.setEL(key,value);
393                return setEL(index, value);
394                    
395            }
396    
397            public Object setEL(Collection.Key key, Object value) {
398                int index=Caster.toIntValue(key.getString(),Integer.MIN_VALUE);
399                    if(index==Integer.MIN_VALUE) query.setEL(key,value);
400                return setEL(index, value);
401            }
402    
403            /**
404             * @see railo.runtime.type.QueryColumn#setEL(int, java.lang.Object)
405             */
406            public synchronized Object setEL(int row, Object value) {
407            // query.disconnectCache();
408            if(row<1 || row>size) return value;
409                
410                value=reDefineType(value);
411                data[row-1]=value;
412                return value;
413            }
414    
415        /**
416             * @see railo.runtime.type.QueryColumn#add(java.lang.Object)
417             */
418            public synchronized void add(Object value) {
419            // query.disconnectCache();
420            if(data.length<=size) growTo(size);
421                data[size++]=value;
422            }
423    
424        /**
425         * @see railo.runtime.type.QueryColumn#cutRowsTo(int)
426         */
427        public synchronized void cutRowsTo(int maxrows) {
428            // query.disconnectCache();
429            if(maxrows>-1 && maxrows<size)size=maxrows;
430        }
431    
432            /**
433             * @see railo.runtime.type.QueryColumn#addRow(int)
434             */
435            public synchronized void addRow(int count) {        
436            // query.disconnectCache();
437            if(data.length<(size+count)) growTo(size+count);
438                for(int i=0;i<count;i++)size++;
439            }
440    
441        public synchronized Object removeRow(int row) throws DatabaseException {
442            // query.disconnectCache();
443            if(row<1 || row>size) 
444                throw new DatabaseException("invalid row number ["+row+"]","valid rows goes from 1 to "+size,null,null,null);
445            Object o=data[row-1];
446            for(int i=row;i<size;i++) {
447                data[i-1]=data[i];
448            }
449            size--;
450            
451            return o==null?"":o;
452        }
453    
454            /**
455             * @param reorganize 
456             * @see railo.runtime.type.QueryColumn#getType()
457             */
458            public int getType() {
459                reOrganizeType();
460                    return type;
461            }
462            
463            
464        /**
465             * @see railo.runtime.type.QueryColumn#getTypeAsString()
466             */
467            public String getTypeAsString() {
468                    return QueryImpl.getColumTypeName(getType());
469            }
470    
471    
472            /**
473             * @see railo.runtime.dump.Dumpable#toDumpData(railo.runtime.PageContext, int)
474             */
475            public DumpData toDumpData(PageContext pageContext, int maxlevel, DumpProperties dp) {
476                    return DumpUtil.toDumpData(get(query.getCurrentrow()), pageContext,maxlevel,dp);
477            }       
478            
479        private synchronized void growTo(int row) {
480            
481            int newSize=(data.length+1)*2;
482            while(newSize<=row) {
483                //print.ln(newSize+"<="+row);
484                newSize*=2;
485            }
486            
487            Object[] newData=new Object[newSize];
488            for(int i=0;i<data.length;i++) {
489                newData[i]=data[i];
490            }
491            data=newData;
492        }
493        
494        private Object reDefineType(Object value) {
495            return QueryColumnUtil.reDefineType(this,value);
496        }
497        
498        private synchronized void resetType() {
499            QueryColumnUtil.resetType(this);
500        }
501        
502        private synchronized void reOrganizeType() {
503            QueryColumnUtil.reOrganizeType(this);
504        }
505    
506        public Collection.Key getKey() {
507            return key;
508        }
509        public void setKey(Collection.Key key) {
510            this.key = key;
511        }
512    
513            /**
514             * @see railo.runtime.type.ref.Reference#getKeyAsString()
515             */
516            public String getKeyAsString() throws PageException {
517                    return key.getLowerString();// TODO ist das OK?
518            }
519    
520        /**
521         * @see railo.runtime.type.ref.Reference#get(railo.runtime.PageContext)
522         */
523        public Object get(PageContext pc) {
524            return get(query.getCurrentrow());
525        }
526        
527        /**
528         *
529         * @see railo.runtime.type.ref.Reference#get(railo.runtime.PageContext, java.lang.Object)
530         */
531        public Object get(PageContext pc, Object defaultValue) {
532            return get(query.getCurrentrow(),defaultValue);
533        }
534    
535        /**
536         * @see railo.runtime.type.ref.Reference#touch(railo.runtime.PageContext)
537         */
538        public Object touch(PageContext pc) throws PageException {
539            return touch(query.getCurrentrow());
540        }
541    
542        public Object touchEL(PageContext pc) {
543            return touchEL(query.getCurrentrow());
544        }
545    
546        /**
547         * @see railo.runtime.type.ref.Reference#set(railo.runtime.PageContext, java.lang.Object)
548         */
549        public Object set(PageContext pc, Object value) throws PageException {
550            return set(query.getCurrentrow(),value);
551        }
552    
553        /**
554         * @see railo.runtime.type.ref.Reference#setEL(railo.runtime.PageContext, java.lang.Object)
555         */
556        public Object setEL(PageContext pc, Object value) {
557            return setEL(query.getCurrentrow(),value);
558        }
559    
560        /**
561         * @see railo.runtime.type.ref.Reference#getParent()
562         */
563        public Object getParent() {
564            return query;
565        }
566    
567        /**
568         * @see railo.runtime.op.Castable#castToString()
569         */
570        public String castToString() throws PageException {
571            return Caster.toString(get(query.getCurrentrow()));
572        }
573    
574            /**
575             * @see railo.runtime.op.Castable#castToString(java.lang.String)
576             */
577            public String castToString(String defaultValue) {
578                    Object value = get(query.getCurrentrow(),null);
579                    if(value==null) return defaultValue;
580                    return Caster.toString(value,defaultValue);
581            }
582    
583        /**
584         * @see railo.runtime.op.Castable#castToBooleanValue()
585         */
586        public boolean castToBooleanValue() throws PageException {
587            return Caster.toBooleanValue(get(query.getCurrentrow()));
588        }
589        
590        /**
591         * @see railo.runtime.op.Castable#castToBoolean(java.lang.Boolean)
592         */
593        public Boolean castToBoolean(Boolean defaultValue) {
594            Object value = get(query.getCurrentrow(),null);
595                    if(value==null) return defaultValue;
596                    return Caster.toBoolean(value,defaultValue);
597        }
598    
599        /**
600         * @see railo.runtime.op.Castable#castToDoubleValue()
601         */
602        public double castToDoubleValue() throws PageException {
603            return Caster.toDoubleValue(get(query.getCurrentrow()));
604        }
605        
606        /**
607         * @see railo.runtime.op.Castable#castToDoubleValue(double)
608         */
609        public double castToDoubleValue(double defaultValue) {
610            Object value = get(query.getCurrentrow(),null);
611                    if(value==null) return defaultValue;
612                    return Caster.toDoubleValue(value,defaultValue);
613        }
614    
615        /**
616         * @see railo.runtime.op.Castable#castToDateTime()
617         */
618        public DateTime castToDateTime() throws PageException {
619            return DateCaster.toDateAdvanced(get(query.getCurrentrow()),null);
620        }
621        
622        /**
623         * @see railo.runtime.op.Castable#castToDateTime(railo.runtime.type.dt.DateTime)
624         */
625        public DateTime castToDateTime(DateTime defaultValue) {
626            Object value = get(query.getCurrentrow(),null);
627                    if(value==null) return defaultValue;
628                    return DateCaster.toDateAdvanced(value,true,null,defaultValue);
629        }
630    
631    
632            /**
633             * @see railo.runtime.op.Castable#compare(boolean)
634             */
635            public int compareTo(boolean b) throws PageException {
636                    return Operator.compare(castToBooleanValue(), b);
637            }
638    
639            /**
640             * @see railo.runtime.op.Castable#compareTo(railo.runtime.type.dt.DateTime)
641             */
642            public int compareTo(DateTime dt) throws PageException {
643                    return Operator.compare((Date)castToDateTime(), (Date)dt);
644            }
645    
646            /**
647             * @see railo.runtime.op.Castable#compareTo(double)
648             */
649            public int compareTo(double d) throws PageException {
650                    return Operator.compare(castToDoubleValue(), d);
651            }
652    
653            /**
654             * @see railo.runtime.op.Castable#compareTo(java.lang.String)
655             */
656            public int compareTo(String str) throws PageException {
657                    return Operator.compare(castToString(), str);
658            }
659    
660        /**
661         * @see railo.runtime.type.Collection#clone()
662         */
663        public synchronized Object clone() {
664            return duplicate(true);
665        }
666    
667        public synchronized Collection duplicate(boolean deepCopy) {
668            return cloneColumn(query,deepCopy);
669        }
670        
671        public synchronized QueryColumnPro cloneColumn(QueryImpl query, boolean deepCopy) {
672            QueryColumnImpl clone=new QueryColumnImpl();
673            populate(this, clone, deepCopy);
674            return clone;
675        }
676        
677        protected static void populate(QueryColumnImpl src,QueryColumnImpl trg, boolean deepCopy) {
678            
679            ThreadLocalDuplication.set(src, trg);
680            try{
681                    trg.key=src.key;
682                    trg.query=src.query;
683                    trg.size=src.size;
684                    trg.type=src.type;
685                    trg.key=src.key;
686                    
687                    trg.data=new Object[src.data.length];
688                    for(int i=0;i<src.data.length;i++) {
689                        trg.data[i]=deepCopy?Duplicator.duplicate(src.data[i],true):src.data[i];
690                    }
691            }
692            finally {
693                    ThreadLocalDuplication.remove(src);
694            }
695        }
696            
697    
698        /**
699         * @see java.lang.Object#toString()
700         */
701        public String toString() {
702            try {
703                return Caster.toString(get(query.getCurrentrow()));
704            } catch (PageException e) {
705                return super.toString();
706            }
707        }
708    
709        /**
710         * @see railo.runtime.type.Collection#containsKey(java.lang.String)
711         */
712        public boolean containsKey(String key) {
713            return get(key,null)!=null;
714        }
715    
716            /**
717             *
718             * @see railo.runtime.type.Collection#containsKey(railo.runtime.type.Collection.Key)
719             */
720            public boolean containsKey(Collection.Key key) {
721            return get(key,null)!=null;
722            }
723    
724            /**
725             * @see railo.runtime.type.Sizeable#sizeOf()
726             */
727            public long sizeOf() {
728                    return SizeOf.size(key)+SizeOf.size(data);
729            }
730            
731            /**
732             *
733             * @see railo.runtime.type.Iteratorable#iterator()
734             */
735            public Iterator iterator() {
736                    return keyIterator();
737            }
738    
739            /**
740             * @see railo.runtime.type.Collection#keyIterator()
741             */
742            public Iterator keyIterator() {
743                    return new KeyIterator(keys());
744            }
745    
746            /**
747             * @see railo.runtime.type.Iteratorable#valueIterator()
748             */
749            public Iterator valueIterator() {
750                    return new ArrayIterator(data,0,size);
751            }
752            
753            /**
754             * @see railo.runtime.type.Objects#callWithNamedValues(railo.runtime.PageContext, railo.runtime.type.Collection.Key, railo.runtime.type.Struct)
755             */
756            public Object callWithNamedValues(PageContext pc, Key methodName,Struct args) throws PageException {
757                    
758            throw new ExpressionException("No matching Method/Function ["+methodName+"] for call with named arguments found");
759                    //return pc.getFunctionWithNamedValues(get(query.getCurrentrow()), methodName, Caster.toFunctionValues(args));
760            }
761    
762            /**
763             * @see railo.runtime.type.Objects#call(railo.runtime.PageContext, railo.runtime.type.Collection.Key, java.lang.Object[])
764             */
765            public Object call(PageContext pc, Key methodName, Object[] arguments) throws PageException {
766                    MethodInstance mi = Reflector.getMethodInstanceEL(this.getClass(), methodName, arguments);
767                    if(mi!=null) {
768                            try {
769                                    return mi.invoke(this);
770                            } catch (Throwable t) {
771                                    try {
772                                            return pc.getFunction(get(query.getCurrentrow()), methodName, arguments);
773                                    } catch (PageException pe) {
774                                            throw Caster.toPageException(t);
775                                    }
776                            }
777                    }
778                    return pc.getFunction(get(query.getCurrentrow()), methodName, arguments);
779            }
780    
781            /**
782             * @see railo.runtime.type.Objects#call(railo.runtime.PageContext, java.lang.String, java.lang.Object[])
783             */
784            public Object call(PageContext pc, String methodName, Object[] arguments)throws PageException {
785                    return call(pc, KeyImpl.init(methodName), arguments);
786            }
787    
788            /**
789             * @see railo.runtime.type.Objects#callWithNamedValues(railo.runtime.PageContext, java.lang.String, railo.runtime.type.Struct)
790             */
791            public Object callWithNamedValues(PageContext pc, String methodName,Struct args) throws PageException {
792                    return callWithNamedValues(pc, KeyImpl.init(methodName), args);
793            }
794    
795            /**
796             * @see railo.runtime.type.Objects#get(railo.runtime.PageContext, railo.runtime.type.Collection.Key, java.lang.Object)
797             */
798            public Object get(PageContext pc, Key key, Object defaultValue) {
799                    return get(key,defaultValue);
800            }
801    
802            /**
803             * @see railo.runtime.type.Objects#get(railo.runtime.PageContext, railo.runtime.type.Collection.Key)
804             */
805            public Object get(PageContext pc, Key key) throws PageException {
806                    return get(key);
807            }
808    
809            /**
810             * @see railo.runtime.type.Objects#isInitalized()
811             */
812            public boolean isInitalized() {
813                    return true;
814            }
815    
816            /**
817             * @see railo.runtime.type.Objects#set(railo.runtime.PageContext, java.lang.String, java.lang.Object)
818             */
819            public Object set(PageContext pc, String propertyName, Object value)throws PageException {
820                    return set(propertyName, value);
821            }
822    
823            /**
824             * @see railo.runtime.type.Objects#set(railo.runtime.PageContext, railo.runtime.type.Collection.Key, java.lang.Object)
825             */
826            public Object set(PageContext pc, Key propertyName, Object value) throws PageException {
827                    return set(propertyName, value);
828            }
829    
830            /**
831             * @see railo.runtime.type.Objects#setEL(railo.runtime.PageContext, java.lang.String, java.lang.Object)
832             */
833            public Object setEL(PageContext pc, String propertyName, Object value) {
834                    return setEL(key, value);
835            }
836    
837            /**
838             * @see railo.runtime.type.Objects#setEL(railo.runtime.PageContext, railo.runtime.type.Collection.Key, java.lang.Object)
839             */
840            public Object setEL(PageContext pc, Key propertyName, Object value) {
841                    return setEL(propertyName, value);
842            }
843    
844            /**
845             * @see java.util.List#add(int, java.lang.Object)
846             */
847            public void add(int index, Object element) {
848                    throwNotAllowedToAlter();
849                    //setEL(index+1, element);
850            }
851    
852            private void throwNotAllowedToAlter() {
853                    throw new PageRuntimeException(new DatabaseException(
854                                    "Query columns do not support methods that would alter the structure of a query column" 
855                                    ,"you must use an analogous method on the query"
856                                    ,null
857                                    ,null
858                                    ,null));
859                    
860            }
861    
862            /**
863             * @see java.util.List#addAll(java.util.Collection)
864             */
865            public boolean addAll(java.util.Collection<? extends Object> c) {
866                    throwNotAllowedToAlter();
867                    return false;
868                    /*Iterator<? extends Object> it = c.iterator();
869                    while(it.hasNext()){
870                            add(it.next());
871                    }
872                    return true;*/
873            }
874    
875            /**
876             * @see java.util.List#addAll(int, java.util.Collection)
877             */
878            public boolean addAll(int index, java.util.Collection<? extends Object> c) {
879                    throwNotAllowedToAlter();
880                    return false;
881                    /*Iterator<? extends Object> it = c.iterator();
882                    while(it.hasNext()){
883                            setEL(++index,it.next());
884                    }
885                    return true;*/
886            }
887    
888            /**
889             * @see java.util.List#contains(java.lang.Object)
890             */
891            public boolean contains(Object o) {
892                    return indexOf(o)!=-1;
893            }
894    
895            /**
896             * @see java.util.List#containsAll(java.util.Collection)
897             */
898            public boolean containsAll(java.util.Collection<?> c) {
899                    Iterator<? extends Object> it = c.iterator();
900                    while(it.hasNext()){
901                            if(indexOf(it.next())==-1) return false;
902                    }
903                    return true;
904            }
905    
906            /**
907             * @see java.util.List#indexOf(java.lang.Object)
908             */
909            public int indexOf(Object o) {
910                    for(int i=0;i<size;i++){
911                            try {
912                                    if(Operator.compare(o, data[i])==0) return i;
913                            } 
914                            catch (PageException e) {}
915                    }
916                    return -1;
917            }
918    
919            /**
920             * @see java.util.List#lastIndexOf(java.lang.Object)
921             */
922            public int lastIndexOf(Object o) {
923                    for(int i=size-1;i>=0;i--){
924                            try {
925                                    if(Operator.compare(o, data[i])==0) return i;
926                            } 
927                            catch (PageException e) {}
928                    }
929                    return -1;
930            }
931    
932            /**
933             * @see java.util.List#isEmpty()
934             */
935            public boolean isEmpty() {
936                    return size()==0;
937            }
938    
939            /*public ListIterator<Object> listIterator() {
940                    return null;
941            }
942    
943            public ListIterator<Object> listIterator(int index) {
944                    return null;
945            }*/
946    
947            /**
948             * @see java.util.List#removeAll(java.util.Collection)
949             */
950            public boolean removeAll(java.util.Collection<?> c) {
951                    throwNotAllowedToAlter();
952                    return false;
953                    /*boolean hasChanged=false;
954                    Iterator<? extends Object> it = c.iterator();
955                    while(it.hasNext()){
956                            if(remove(it.next())) {
957                                    hasChanged=true;
958                            }
959                    }
960                    return hasChanged;*/
961            }
962    
963            /**
964             * @see java.util.List#retainAll(java.util.Collection)
965             */
966            public boolean retainAll(java.util.Collection<?> c) {
967                    throwNotAllowedToAlter();
968                    return false;
969                    /*boolean hasChanged=false;
970                    Iterator it = valueIterator();
971                    while(it.hasNext()){
972                            if(!c.contains(it.next())){
973                                    hasChanged=true;
974                                    it.remove();
975                            }
976                    }
977                    return hasChanged;*/
978            }
979    
980            /**
981             * @see java.util.List#subList(int, int)
982             */
983            public List<Object> subList(int fromIndex, int toIndex) {
984                    ArrayList<Object> list=new ArrayList<Object>();
985                    for(int i=fromIndex;i<toIndex;i++){
986                            list.add(data[i]);
987                    }
988                    return list;
989            }
990    
991            /**
992             * @see java.util.List#toArray()
993             */
994            public Object[] toArray() {
995                    return toArray(new Object[size()]);
996            }
997    
998            /**
999             * @see java.util.List#toArray(T[])
1000             */
1001            public  Object[] toArray(Object[] trg) {
1002                    System.arraycopy(data, 0, trg, 0, data.length>trg.length?trg.length:data.length);
1003                    return trg;
1004            }
1005    
1006    
1007            public boolean equals(Object obj){
1008                    if(!(obj instanceof Collection)) return false;
1009                    return CollectionUtil.equals(this,(Collection)obj);
1010            }
1011    
1012            @Override
1013            public QueryColumnPro toDebugColumn() {
1014                    return new DebugQueryColumn(data,key,query,size,type,typeChecked);
1015            }
1016    }