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