001    package railo.runtime.type.util;
002    
003    import java.sql.Types;
004    import java.text.Collator;
005    import java.util.ArrayList;
006    import java.util.Comparator;
007    import java.util.Iterator;
008    import java.util.List;
009    import java.util.ListIterator;
010    import java.util.Map;
011    import java.util.Set;
012    
013    import railo.commons.lang.ArrayUtilException;
014    import railo.commons.lang.SizeOf;
015    import railo.commons.lang.StringUtil;
016    import railo.runtime.PageContext;
017    import railo.runtime.engine.ThreadLocalPageContext;
018    import railo.runtime.exp.CasterException;
019    import railo.runtime.exp.ExpressionException;
020    import railo.runtime.exp.PageException;
021    import railo.runtime.op.Caster;
022    import railo.runtime.op.Decision;
023    import railo.runtime.op.Operator;
024    import railo.runtime.type.Array;
025    import railo.runtime.type.QueryColumn;
026    import railo.runtime.type.comparator.NumberComparator;
027    import railo.runtime.type.comparator.SortRegister;
028    import railo.runtime.type.comparator.TextComparator;
029    
030    /**
031     * Util for diffrent methods to manipulate arrays
032     */
033    public final class ArrayUtil {
034        
035        public static final Object[] OBJECT_EMPTY = new Object[]{};
036            
037        /**
038         * trims all value of a String Array
039         * @param arr
040         * @return trimmed array
041         */
042        public static String[] trim(String[] arr) {
043            for(int i=0;i<arr.length;i++) {
044                arr[i]=arr[i].trim();
045            }
046            return arr;
047        }
048        
049        
050            /**
051             * @param list
052             * @return array
053             */
054            public static SortRegister[] toSortRegisterArray(ArrayList list) {
055                    SortRegister[] arr=new SortRegister[list.size()];
056                    for(int i=0;i<arr.length;i++) {
057                            arr[i]=new SortRegister(i,list.get(i));
058                    }
059                    return arr;
060            }
061    
062            /**
063             * @param column
064             * @return array
065             */
066            public static SortRegister[] toSortRegisterArray(QueryColumn column) {
067                    SortRegister[] arr=new SortRegister[column.size()];
068                    int type = column.getType();
069                    for(int i=0;i<arr.length;i++) {
070                            arr[i]=new SortRegister(i,toSortRegisterArray(column.get(i+1,null),type));
071                    }
072                    return arr;
073            }
074            
075            private static Object toSortRegisterArray(Object value, int type) {
076                    
077                    Object mod=null;
078                // Date
079                if(Types.TIMESTAMP==type) {
080                    mod= Caster.toDate(value, true, null,null);
081                }
082                // Double
083                else if(Types.DOUBLE==type) {
084                    mod= Caster.toDouble(value,null);
085                }
086                // Boolean
087                else if(Types.BOOLEAN==type) {
088                    mod= Caster.toBoolean(value,null);
089                }
090                // Varchar
091                else if(Types.VARCHAR==type) {
092                    mod= Caster.toString(value,null);
093                }
094                else return value;
095                
096                if(mod!=null) return mod;
097                return value;
098            }
099            
100            /**
101             * swap to values of the array
102             * @param array
103             * @param left left value to swap
104             * @param right right value to swap
105             * @throws ExpressionException
106             */
107            public static void swap(Array array, int left, int right) throws ExpressionException {
108                    int len=array.size();
109                    if(len==0)
110                            throw new ExpressionException("array is empty");
111                    if(left<1 || left>len)
112                            throw new ExpressionException("invalid index ["+left+"]","valid indexes are from 1 to "+len);
113                    if(right<1 || right>len)
114                            throw new ExpressionException("invalid index ["+right+"]","valid indexes are from 1 to "+len);
115                    
116                    try {
117                            Object leftValue=array.get(left,null);
118                            Object rightValue=array.get(right,null);
119                            array.setE(left,rightValue);
120                            array.setE(right,leftValue);
121                    } catch (PageException e) {
122                            throw new ExpressionException("can't swap values of array",e.getMessage());
123                    }
124                    
125            }
126            
127            /**
128             * find a object in array
129             * @param array
130             * @param object object to find
131             * @return position in array or 0
132             */
133            public static int find(Array array, Object object) {
134                    int len=array.size();
135                    for(int i=1;i<=len;i++) {
136                            Object tmp=array.get(i,null);
137                            try {
138                                    if(tmp !=null && Operator.compare(object,tmp)==0)
139                                            return i;
140                            } catch (PageException e) {}
141                    }
142                    return 0;
143            }
144            
145            /**
146             * average of all values of the array, only work when all values are numeric
147             * @param array
148             * @return average of all values
149             * @throws ExpressionException
150            */
151            public static double avg(Array array) throws ExpressionException {
152                    if(array.size()==0)return 0;
153                    return sum(array)/array.size();
154            }
155            
156            /**
157             * sum of all values of a array, only work when all values are numeric
158             * @param array Array 
159             * @return sum of all values
160             * @throws ExpressionException
161            */
162            public static double sum(Array array) throws ExpressionException {
163                    if(array.getDimension()>1)
164                            throw new ExpressionException("can only get sum/avg from 1 dimensional arrays");
165                    
166                    double rtn=0;
167                    int len=array.size();
168                    //try {                 
169                            for(int i=1;i<=len;i++) {
170                                    rtn+=_toDoubleValue(array,i);
171                            }
172                    /*} 
173                    catch (PageException e) {
174                            throw new ExpressionException("exception while execute array operation: "+e.getMessage());
175                    }*/
176                    return rtn;
177            }
178            
179            private static double _toDoubleValue(Array array, int i) throws ExpressionException {
180                    Object obj = array.get(i,null);
181                    if(obj==null)throw new ExpressionException("there is no element at position ["+i+"] or the element is null");
182                    double tmp = Caster.toDoubleValue(obj,Double.NaN);
183                    if(Double.isNaN(tmp))
184                            throw new CasterException(obj,Double.class);
185                    return tmp;
186            }
187    
188    
189            /**
190             * the smallest value, of all values inside the array, only work when all values are numeric
191             * @param array
192             * @return the smallest value
193             * @throws PageException 
194            */
195            public static double min(Array array) throws PageException {
196                    if(array.getDimension()>1)
197                            throw new ExpressionException("can only get max value from 1 dimensional arrays");
198                    if(array.size()==0) return 0;
199                    
200                    double rtn=_toDoubleValue(array,1);
201                    int len=array.size();
202                    try {
203                            for(int i=2;i<=len;i++) {
204                                    double v=_toDoubleValue(array,i);
205                                    if(rtn>v)rtn=v;
206                                    
207                            }
208                    } catch (PageException e) {
209                            throw new ExpressionException("exception while execute array operation: "+e.getMessage());
210                    }
211                    return rtn;
212            }
213            
214            /**
215             * the greatest value, of all values inside the array, only work when all values are numeric
216             * @param array
217             * @return the greatest value
218             * @throws PageException 
219            */
220            public static double max(Array array) throws PageException {
221                    if(array.getDimension()>1)
222                            throw new ExpressionException("can only get max value from 1 dimensional arrays");
223                    if(array.size()==0) return 0;
224                    
225                    double rtn=_toDoubleValue(array,1);
226                    int len=array.size();
227                    try {
228                            for(int i=2;i<=len;i++) {
229                                    double v=_toDoubleValue(array,i);
230                                    if(rtn<v)rtn=v;
231                                    
232                            }
233                    } catch (PageException e) {
234                            throw new ExpressionException("exception while execute array operation: "+e.getMessage());
235                    }
236                    return rtn;
237            }
238            
239            /**
240             * return index of given value in Array or -1
241             * @param arr
242             * @param value
243             * @return index of position in array
244             */
245            public static int indexOf(String[] arr, String value) {
246                for(int i=0;i<arr.length;i++) {
247                    if(arr[i].equals(value)) return i;
248                }
249                return -1;
250            }
251            
252            /**
253             * return index of given value in Array or -1
254             * @param arr
255             * @param value
256             * @return index of position in array
257             */
258            public static int indexOfIgnoreCase(String[] arr, String value) {
259                for(int i=0;i<arr.length;i++) {
260                    if(arr[i].equalsIgnoreCase(value)) return i;
261                }
262                return -1;
263            }
264            
265            
266    
267            /**
268             * convert a primitive array (value type) to Object Array (reference type).
269             * @param primArr value type Array 
270             * @return reference type Array
271             */
272            public static Boolean[] toReferenceType(boolean[] primArr) {
273                    Boolean[] refArr=new Boolean[primArr.length];
274                    for(int i=0;i<primArr.length;i++)refArr[i]=Caster.toBoolean(primArr[i]);
275                    return refArr;
276            }
277            
278            /**
279             * convert a primitive array (value type) to Object Array (reference type).
280             * @param primArr value type Array 
281             * @return reference type Array
282             */
283            public static Byte[] toReferenceType(byte[] primArr) {
284                    Byte[] refArr=new Byte[primArr.length];
285                    for(int i=0;i<primArr.length;i++)refArr[i]=new Byte(primArr[i]);
286                    return refArr;
287            }
288            
289            /**
290             * convert a primitive array (value type) to Object Array (reference type).
291             * @param primArr value type Array 
292             * @return reference type Array
293             */
294            public static Character[] toReferenceType(char[] primArr) {
295                    Character[] refArr=new Character[primArr.length];
296                    for(int i=0;i<primArr.length;i++)refArr[i]=new Character(primArr[i]);
297                    return refArr;
298            }
299            
300            /**
301             * convert a primitive array (value type) to Object Array (reference type).
302             * @param primArr value type Array 
303             * @return reference type Array
304             */
305            public static Short[] toReferenceType(short[] primArr) {
306                    Short[] refArr=new Short[primArr.length];
307                    for(int i=0;i<primArr.length;i++)refArr[i]=Short.valueOf(primArr[i]);
308                    return refArr;
309            }
310            
311            /**
312             * convert a primitive array (value type) to Object Array (reference type).
313             * @param primArr value type Array 
314             * @return reference type Array
315             */
316            public static Integer[] toReferenceType(int[] primArr) {
317                    Integer[] refArr=new Integer[primArr.length];
318                    for(int i=0;i<primArr.length;i++)refArr[i]=Integer.valueOf(primArr[i]);
319                    return refArr;
320            }
321            
322            /**
323             * convert a primitive array (value type) to Object Array (reference type).
324             * @param primArr value type Array 
325             * @return reference type Array
326             */
327            public static Long[] toReferenceType(long[] primArr) {
328                    Long[] refArr=new Long[primArr.length];
329                    for(int i=0;i<primArr.length;i++)refArr[i]=Long.valueOf(primArr[i]);
330                    return refArr;
331            }
332            
333            /**
334             * convert a primitive array (value type) to Object Array (reference type).
335             * @param primArr value type Array 
336             * @return reference type Array
337             */
338            public static Float[] toReferenceType(float[] primArr) {
339                    Float[] refArr=new Float[primArr.length];
340                    for(int i=0;i<primArr.length;i++)refArr[i]=new Float(primArr[i]);
341                    return refArr;
342            }
343            
344            /**
345             * convert a primitive array (value type) to Object Array (reference type).
346             * @param primArr value type Array 
347             * @return reference type Array
348             */
349            public static Double[] toReferenceType(double[] primArr) {
350                    Double[] refArr=new Double[primArr.length];
351                    for(int i=0;i<primArr.length;i++)refArr[i]=new Double(primArr[i]);
352                    return refArr;
353            }
354    
355            /**
356             * gets a value of a array at defined index
357             * @param o
358             * @param index
359             * @return value at index position
360             * @throws ArrayUtilException
361             */
362            public static Object get(Object o,int index) throws ArrayUtilException {
363                o=get(o,index,null);
364                    if(o!=null) return o;
365                    throw new ArrayUtilException("Object is not a array, or index is invalid");
366            }
367            
368            /**
369             * gets a value of a array at defined index
370             * @param o
371             * @param index
372             * @return value of the variable
373             */
374            public static Object get(Object o,int index, Object defaultValue) {
375                if(index<0) return null;
376                if(o instanceof Object[])   {
377                        Object[] arr=((Object[])o);
378                        if(arr.length>index)return arr[index];
379                    }
380                else if(o instanceof boolean[])     {
381                    boolean[] arr=((boolean[])o);
382                        if(arr.length>index)return arr[index]?Boolean.TRUE:Boolean.FALSE;
383                    }
384                else if(o instanceof byte[])        {
385                    byte[] arr=((byte[])o);
386                        if(arr.length>index)return new Byte(arr[index]);
387                    }
388                else if(o instanceof char[])        {
389                    char[] arr=((char[])o);
390                        if(arr.length>index)return ""+(arr[index]);
391                    }
392                else if(o instanceof short[])       {
393                    short[] arr=((short[])o);
394                        if(arr.length>index)return Short.valueOf(arr[index]);
395                    }
396                else if(o instanceof int[]) {
397                    int[] arr=((int[])o);
398                        if(arr.length>index)return Integer.valueOf(arr[index]);
399                    }
400                else if(o instanceof long[])        {
401                    long[] arr=((long[])o);
402                        if(arr.length>index)return Long.valueOf(arr[index]);
403                    }
404                else if(o instanceof float[])       {
405                    float[] arr=((float[])o);
406                        if(arr.length>index)return new Float(arr[index]);
407                    }
408                else if(o instanceof double[])      {
409                    double[] arr=((double[])o);
410                        if(arr.length>index)return new Double(arr[index]);
411                    }
412                    return defaultValue;
413            }
414    
415            /**
416             * sets a value to a array at defined index
417             * @param o
418             * @param index
419             * @param value
420             * @return value setted
421             * @throws ArrayUtilException
422             */
423            public static Object set(Object o,int index, Object value) throws ArrayUtilException {
424                if(index<0) 
425                        throw invalidIndex(index,0);
426                if(o instanceof Object[])   {
427                        Object[] arr=((Object[])o);
428                        if(arr.length>index)return arr[index]=value;
429                        throw invalidIndex(index,arr.length);
430                    }
431                else if(o instanceof boolean[])     {
432                    boolean[] arr=((boolean[])o);
433                    if(arr.length>index) {
434                        arr[index]=Caster.toBooleanValue(value,false);
435                        return arr[index]?Boolean.TRUE:Boolean.FALSE;
436                    }
437                        throw invalidIndex(index,arr.length);
438                    }
439                else if(o instanceof byte[])        {
440                    byte[] arr=((byte[])o);
441                    if(arr.length>index) {
442                        double v=Caster.toDoubleValue(value,Double.NaN);
443                        if(Decision.isValid(v)) {
444                            return new Byte(arr[index]=(byte)v);
445                        }
446                    }
447                        throw invalidIndex(index,arr.length);
448                    }
449                else if(o instanceof short[])       {
450                    short[] arr=((short[])o);
451                    if(arr.length>index) {
452                        double v=Caster.toDoubleValue(value,Double.NaN);
453                        if(Decision.isValid(v)) {
454                            return Short.valueOf(arr[index]=(short)v);
455                        }
456                    }
457                        throw invalidIndex(index,arr.length);
458                    }
459                else if(o instanceof int[]) {
460                    int[] arr=((int[])o);
461                    if(arr.length>index) {
462                        double v=Caster.toDoubleValue(value,Double.NaN);
463                        if(Decision.isValid(v)) {
464                            return Integer.valueOf(arr[index]=(int)v);
465                        }
466                    }
467                        throw invalidIndex(index,arr.length);
468                    }
469                else if(o instanceof long[])        {
470                    long[] arr=((long[])o);
471                    if(arr.length>index) {
472                        double v=Caster.toDoubleValue(value,Double.NaN);
473                        if(Decision.isValid(v)) {
474                            return Long.valueOf(arr[index]=(long)v);
475                        }
476                    }
477                        throw invalidIndex(index,arr.length);
478                    }
479                else if(o instanceof float[])       {
480                    float[] arr=((float[])o);
481                    if(arr.length>index) {
482                        double v=Caster.toDoubleValue(value,Double.NaN);
483                        if(Decision.isValid(v)) {
484                            return new Float(arr[index]=(float)v);
485                        }
486                    }
487                        throw invalidIndex(index,arr.length);
488                    }
489                else if(o instanceof double[])      {
490                    double[] arr=((double[])o);
491                    if(arr.length>index) {
492                        double v=Caster.toDoubleValue(value,Double.NaN);
493                        if(Decision.isValid(v)) {
494                            return new Double(arr[index]=v);
495                        }
496                    }
497                        throw invalidIndex(index,arr.length);
498                    }
499                else if(o instanceof char[])        {
500                    char[] arr=((char[])o);
501                    if(arr.length>index) {
502                        String str=Caster.toString(value,null);
503                        if(str!=null && str.length()>0) {
504                            char c=str.charAt(0);
505                            arr[index]=c;
506                            return str;
507                        }
508                    }
509                        throw invalidIndex(index,arr.length);
510                    }
511                    throw new ArrayUtilException("Object ["+Caster.toClassName(o)+"] is not a Array");
512            }
513    
514            
515        private static ArrayUtilException invalidIndex(int index, int length) {
516            return new ArrayUtilException("Invalid index ["+index+"] for native Array call, Array has a Size of "+length);
517        }
518    
519        /**
520             * sets a value to a array at defined index
521             * @param o
522             * @param index
523             * @param value
524             * @return value setted
525             */
526            public static Object setEL(Object o,int index, Object value) {
527                try {
528                return set(o,index,value);
529            } catch (ArrayUtilException e) {
530                return null;
531            }
532            }
533    
534            public static boolean isEmpty(List list) {
535                    return list==null || list.isEmpty();
536            }
537            
538            public static boolean isEmpty(Object[] array) {
539                    return array==null || array.length==0;
540            }
541            public static boolean isEmpty(boolean[] array) {
542                    return array==null || array.length==0;
543            }
544            public static boolean isEmpty(char[] array) {
545                    return array==null || array.length==0;
546            }
547            public static boolean isEmpty(double[] array) {
548                    return array==null || array.length==0;
549            }
550            public static boolean isEmpty(long[] array) {
551                    return array==null || array.length==0;
552            }
553            public static boolean isEmpty(int[] array) {
554                    return array==null || array.length==0;
555            }
556            public static boolean isEmpty(float[] array) {
557                    return array==null || array.length==0;
558            }
559            public static boolean isEmpty(byte[] array) {
560                    return array==null || array.length==0;
561            }
562    
563            
564            
565            
566            
567            
568            
569    
570    
571    
572            public static int size(Object[] array) {
573                    if(array==null) return 0; 
574                    return  array.length;
575            }
576            public static int size(boolean[] array) {
577                    if(array==null) return 0; 
578                    return  array.length;
579            }
580            public static int size(char[] array) {
581                    if(array==null) return 0; 
582                    return  array.length;
583            }
584            public static int size(double[] array) {
585                    if(array==null) return 0; 
586                    return  array.length;
587            }
588            public static int size(long[] array) {
589                    if(array==null) return 0; 
590                    return  array.length;
591            }
592            public static int size(int[] array) {
593                    if(array==null) return 0; 
594                    return  array.length;
595            }
596            public static int size(float[] array) {
597                    if(array==null) return 0; 
598                    return  array.length;
599            }
600            public static int size(byte[] array) {
601                    if(array==null) return 0; 
602                    return  array.length;
603            }
604    
605    
606            public static boolean[] toBooleanArray(Object obj) throws PageException {
607                    if(obj instanceof boolean[]) return (boolean[]) obj;
608                    
609                    Array arr = Caster.toArray(obj);
610                    boolean[] tarr=new boolean[arr.size()];
611                    for(int i=0;i<tarr.length;i++) {
612                            tarr[i]=Caster.toBooleanValue(arr.getE(i+1));
613                    }
614                    return tarr;
615            }
616    
617            public static byte[] toByteArray(Object obj) throws PageException {
618                    if(obj instanceof byte[]) return (byte[]) obj;
619                    
620                    Array arr = Caster.toArray(obj);
621                    byte[] tarr=new byte[arr.size()];
622                    for(int i=0;i<tarr.length;i++) {
623                            tarr[i]=Caster.toByteValue(arr.getE(i+1));
624                    }
625                    return tarr;
626            }
627            
628            public static short[] toShortArray(Object obj) throws PageException {
629                    if(obj instanceof short[]) return (short[]) obj;
630                    
631                    Array arr = Caster.toArray(obj);
632                    short[] tarr=new short[arr.size()];
633                    for(int i=0;i<tarr.length;i++) {
634                            tarr[i]=Caster.toShortValue(arr.getE(i+1));
635                    }
636                    return tarr;
637            }
638            
639            public static int[] toIntArray(Object obj) throws PageException {
640                    if(obj instanceof int[]) return (int[]) obj;
641                    
642                    Array arr = Caster.toArray(obj);
643                    int[] tarr=new int[arr.size()];
644                    for(int i=0;i<tarr.length;i++) {
645                            tarr[i]=Caster.toIntValue(arr.getE(i+1));
646                    }
647                    return tarr;
648            }
649            
650            public static Object[] toNullArray(Object obj) throws PageException {
651                    Array arr = Caster.toArray(obj);
652                    Object[] tarr=new Object[arr.size()];
653                    for(int i=0;i<tarr.length;i++) {
654                            tarr[i]=Caster.toNull(arr.getE(i+1));
655                    }
656                    return tarr;
657            }
658            
659            public static long[] toLongArray(Object obj) throws PageException {
660                    if(obj instanceof long[]) return (long[]) obj;
661                    
662                    Array arr = Caster.toArray(obj);
663                    long[] tarr=new long[arr.size()];
664                    for(int i=0;i<tarr.length;i++) {
665                            tarr[i]=Caster.toLongValue(arr.getE(i+1));
666                    }
667                    return tarr;
668            }
669    
670            public static float[] toFloatArray(Object obj) throws PageException {
671                    if(obj instanceof float[]) return (float[]) obj;
672                    
673                    Array arr = Caster.toArray(obj);
674                    float[] tarr=new float[arr.size()];
675                    for(int i=0;i<tarr.length;i++) {
676                            tarr[i]=Caster.toFloatValue(arr.getE(i+1));
677                    }
678                    return tarr;
679            }
680            
681            public static double[] toDoubleArray(Object obj) throws PageException {
682                    if(obj instanceof double[]) return (double[]) obj;
683                    
684                    Array arr = Caster.toArray(obj);
685                    double[] tarr=new double[arr.size()];
686                    for(int i=0;i<tarr.length;i++) {
687                            tarr[i]=Caster.toDoubleValue(arr.getE(i+1));
688                    }
689                    return tarr;
690            }
691            
692            public static char[] toCharArray(Object obj) throws PageException {
693                    if(obj instanceof char[]) return (char[]) obj;
694                    
695                    Array arr = Caster.toArray(obj);
696                    char[] tarr=new char[arr.size()];
697                    for(int i=0;i<tarr.length;i++) {
698                            tarr[i]=Caster.toCharValue(arr.getE(i+1));
699                    }
700                    return tarr;
701            }
702    
703    
704            public static int arrayContainsIgnoreEmpty(Array arr, String value, boolean ignoreCase) {
705                    int count=0;
706                    int len=arr.size();
707                    
708                    for(int i=1;i<=len;i++) {
709                            String item=arr.get(i,"").toString();
710                            if(ignoreCase) {
711                                    if(StringUtil.indexOfIgnoreCase(item,value)!=-1) return count;
712                            }
713                            else {
714                                    if(item.indexOf(value)!=-1) return count;
715                            }
716                            count++;
717                    }
718                    return -1;
719            }
720    
721    
722            public static Object[] toReferenceType(Object obj) throws CasterException {
723                    Object[] ref = toReferenceType(obj,null);
724                    if(ref!=null) return ref;
725                    throw new CasterException(obj,Object[].class);
726                    
727            }
728            public static Object[] toReferenceType(Object obj,Object[] defaultValue) {
729                    if(obj instanceof Object[])                     return (Object[])obj;
730                    else if(obj instanceof boolean[])               return toReferenceType((boolean[])obj);
731                    else if(obj instanceof byte[])          return toReferenceType((byte[])obj);
732                    else if(obj instanceof char[])          return toReferenceType((char[])obj);
733                    else if(obj instanceof short[])         return toReferenceType((short[])obj);
734                    else if(obj instanceof int[])                   return toReferenceType((int[])obj);
735                    else if(obj instanceof long[])          return toReferenceType((long[])obj);
736                    else if(obj instanceof float[])         return toReferenceType((float[])obj);
737                    else if(obj instanceof double[])                return toReferenceType((double[])obj);
738                    return defaultValue;
739            }
740    
741    
742            public static Object[] clone(Object[] src, Object[] trg) {
743                    for(int i=0;i<src.length;i++){
744                            trg[i]=src[i];
745                    }
746                    return trg;
747            }
748    
749    
750            public static Object[] keys(Map map) {
751                    if(map==null) return new Object[0];
752                    Set set = map.keySet();
753                    if(set==null) return new Object[0];
754                    Object[] arr = set.toArray();
755                    if(arr==null) return new Object[0];
756                    return arr;
757            }
758            
759            public static Object[] values(Map map) {
760                    if(map==null) return new Object[0];
761                    return map.values().toArray();
762            }
763    
764    
765            public static long sizeOf(List list) {
766                    ListIterator it = list.listIterator();
767                    long size=0;
768                    while(it.hasNext()){
769                            size+=SizeOf.size(it.next());
770                    }
771                    return size;
772            }
773            
774            public static long sizeOf(Array array) {
775                    Iterator it = array.valueIterator();
776                    long size=0;
777                    while(it.hasNext()){
778                            size+=SizeOf.size(it.next());
779                    }
780                    return size;
781            }
782    
783    
784            /**
785             * creates a native array out of the input list, if all values are from the same type, this type is used for the array, otherwise object
786             * @param list
787             */
788            public static Object[] toArray(List<?> list) {
789                    Iterator<?> it = list.iterator();
790                    Class clazz=null;
791                    while(it.hasNext()){
792                            Object v = it.next();
793                            if(v==null) continue;
794                            if(clazz==null) clazz=v.getClass();
795                            else if(clazz!=v.getClass()) return list.toArray();     
796                    }
797                    if(clazz==Object.class || clazz==null) 
798                            return list.toArray();
799                    
800                    Object arr = java.lang.reflect.Array.newInstance(clazz, list.size());
801                    return list.toArray((Object[]) arr);    
802            }
803            
804    
805            public static Comparator toComparator(PageContext pc,String sortType, String sortOrder, boolean localeSensitive) throws PageException {
806                    // check sortorder
807                    boolean isAsc=true;
808                    if(sortOrder.equalsIgnoreCase("asc"))isAsc=true;
809                    else if(sortOrder.equalsIgnoreCase("desc"))isAsc=false;
810                    else throw new ExpressionException("invalid sort order type ["+sortOrder+"], sort order types are [asc and desc]");
811                    
812                    // text
813                    if(sortType.equalsIgnoreCase("text")) {
814                            if(localeSensitive)return toCollator(pc,Collator.IDENTICAL);
815                            return new TextComparator(isAsc,false);
816                    }
817                    // text no case
818                    else if(sortType.equalsIgnoreCase("textnocase")) {
819                            if(localeSensitive)return toCollator(pc,Collator.TERTIARY);
820                            return new TextComparator(isAsc,true);
821                    }
822                    // numeric
823                    else if(sortType.equalsIgnoreCase("numeric")) {
824                            return new NumberComparator(isAsc);
825                    }
826                    else {
827                            throw new ExpressionException("invalid sort type ["+sortType+"], sort types are [text, textNoCase, numeric]");
828                    }       
829            }
830            private static Comparator toCollator(PageContext pc, int strength) {
831                    Collator c=Collator.getInstance(ThreadLocalPageContext.getLocale(pc));
832                    c.setStrength(strength);
833                    c.setDecomposition(Collator.CANONICAL_DECOMPOSITION);
834                    return c;
835            }
836    }