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