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