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