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.util.AbstractList; 022import java.util.Iterator; 023import java.util.List; 024 025import lucee.commons.lang.CFTypes; 026import lucee.runtime.PageContext; 027import lucee.runtime.converter.LazyConverter; 028import lucee.runtime.exp.ExpressionException; 029import lucee.runtime.exp.PageException; 030import lucee.runtime.exp.PageRuntimeException; 031import lucee.runtime.op.Caster; 032import lucee.runtime.type.Array; 033import lucee.runtime.type.Collection; 034import lucee.runtime.type.KeyImpl; 035import lucee.runtime.type.Objects; 036import lucee.runtime.type.Sizeable; 037import lucee.runtime.type.Struct; 038import lucee.runtime.type.dt.DateTime; 039 040public abstract class ArraySupport extends AbstractList implements Array,List,Sizeable,Objects { 041 042 043 public static final short TYPE_OBJECT = 0; 044 public static final short TYPE_BOOLEAN = 1; 045 public static final short TYPE_BYTE = 2; 046 public static final short TYPE_SHORT = 3; 047 public static final short TYPE_INT = 4; 048 public static final short TYPE_LONG = 5; 049 public static final short TYPE_FLOAT = 6; 050 public static final short TYPE_DOUBLE = 7; 051 public static final short TYPE_CHARACTER = 8; 052 public static final short TYPE_STRING = 9; 053 054 @Override 055 public final void add(int index, Object element) { 056 try { 057 insert(index+1, element); 058 } catch (PageException e) { 059 throw new IndexOutOfBoundsException("can't insert value to List at position "+index+", " + 060 "valid values are from 0 to "+(size()-1)+", size is "+size()); 061 } 062 } 063 064 @Override 065 public final boolean addAll(java.util.Collection c) { 066 Iterator it = c.iterator(); 067 while(it.hasNext()) { 068 add(it.next()); 069 } 070 return true; 071 } 072 073 @Override 074 public final boolean remove(Object o) { 075 int index = indexOf(o); 076 if(index==-1) return false; 077 078 try { 079 removeE(index+1); 080 } catch (PageException e) { 081 return false; 082 } 083 return true; 084 } 085 086 @Override 087 public final boolean removeAll(java.util.Collection c) { 088 Iterator it = c.iterator(); 089 boolean rtn=false; 090 while(it.hasNext()) { 091 if(remove(it.next()))rtn=true; 092 } 093 return rtn; 094 } 095 096 @Override 097 public final boolean retainAll(java.util.Collection c) { 098 boolean modified = false; 099 Key[] keys = CollectionUtil.keys(this); 100 Key k; 101 for(int i=keys.length-1;i>=0;i--) { 102 k = keys[i]; 103 if(!c.contains(get(k,null))) { 104 removeEL(k); 105 modified = true; 106 } 107 } 108 return modified; 109 } 110 111 @Override 112 public final Object[] toArray(Object[] a) { 113 if(a==null) return toArray(); 114 115 116 Class trgClass=a.getClass().getComponentType(); 117 short type=TYPE_OBJECT; 118 if(trgClass==Boolean.class) type=TYPE_BOOLEAN; 119 else if(trgClass==Byte.class) type=TYPE_BYTE; 120 else if(trgClass==Short.class) type=TYPE_SHORT; 121 else if(trgClass==Integer.class) type=TYPE_INT; 122 else if(trgClass==Long.class) type=TYPE_LONG; 123 else if(trgClass==Float.class) type=TYPE_FLOAT; 124 else if(trgClass==Double.class) type=TYPE_DOUBLE; 125 else if(trgClass==Character.class) type=TYPE_CHARACTER; 126 else if(trgClass==String.class) type=TYPE_STRING; 127 128 129 Iterator it = iterator(); 130 int i=0; 131 Object o; 132 try { 133 while(it.hasNext()) { 134 o=it.next(); 135 switch(type){ 136 case TYPE_BOOLEAN: 137 o=Caster.toBoolean(o); 138 break; 139 case TYPE_BYTE: 140 o=Caster.toByte(o); 141 break; 142 case TYPE_CHARACTER: 143 o=Caster.toCharacter(o); 144 break; 145 case TYPE_DOUBLE: 146 o=Caster.toDouble(o); 147 break; 148 case TYPE_FLOAT: 149 o=Caster.toFloat(o); 150 break; 151 case TYPE_INT: 152 o=Caster.toInteger(o); 153 break; 154 case TYPE_LONG: 155 o=Caster.toLong(o); 156 break; 157 case TYPE_SHORT: 158 o=Caster.toShort(o); 159 break; 160 case TYPE_STRING: 161 o=Caster.toString(o); 162 break; 163 } 164 a[i++]=o; 165 } 166 } 167 catch(PageException pe){ 168 throw new PageRuntimeException(pe); 169 } 170 return a; 171 } 172 173 @Override 174 public final Object get(int index) { 175 if(index<0) 176 throw new IndexOutOfBoundsException("invalid index defintion ["+index+"], " + 177 "index should be a number between [0 - "+(size()-1)+"], size is "+size()); 178 if(index>=size()) 179 throw new IndexOutOfBoundsException("invalid index ["+index+"] defintion, " + 180 "index should be a number between [0 - "+(size()-1)+"], size is "+size()); 181 182 return get(index+1, null); 183 } 184 185 @Override 186 public final Object remove(int index) { 187 if(index<0) 188 throw new IndexOutOfBoundsException("invalid index defintion ["+index+"], " + 189 "index should be a number between [0 - "+(size()-1)+"], size is "+size()); 190 if(index>=size()) 191 throw new IndexOutOfBoundsException("invalid index ["+index+"] defintion, " + 192 "index should be a number between [0 - "+(size()-1)+"], size is "+size()); 193 194 return removeEL(index+1); 195 } 196 197 @Override 198 public final Object set(int index, Object element) { 199 Object o=get(index); 200 setEL(index+1, element); 201 return o; 202 } 203 204 205 @Override 206 public boolean containsKey(String key) { 207 return get(KeyImpl.init(key),null)!=null; 208 } 209 210 @Override 211 public boolean containsKey(Collection.Key key) { 212 return get(key,null)!=null; 213 } 214 215 @Override 216 public boolean containsKey(int key) { 217 return get(key,null)!=null; 218 } 219 220 221 @Override 222 public String toString() { 223 return LazyConverter.serialize(this); 224 } 225 226 @Override 227 public synchronized Object clone() { 228 return duplicate(true); 229 } 230 231 @Override 232 public String castToString() throws PageException { 233 throw new ExpressionException("Can't cast Complex Object Type Array to String", 234 "Use Built-In-Function \"serialize(Array):String\" to create a String from Array"); 235 } 236 237 @Override 238 public String castToString(String defaultValue) { 239 return defaultValue; 240 } 241 242 243 @Override 244 public boolean castToBooleanValue() throws PageException { 245 throw new ExpressionException("Can't cast Complex Object Type Array to a boolean value"); 246 } 247 248 @Override 249 public Boolean castToBoolean(Boolean defaultValue) { 250 return defaultValue; 251 } 252 253 254 255 @Override 256 public double castToDoubleValue() throws PageException { 257 throw new ExpressionException("Can't cast Complex Object Type Array to a number value"); 258 } 259 260 @Override 261 public double castToDoubleValue(double defaultValue) { 262 return defaultValue; 263 } 264 265 266 267 @Override 268 public DateTime castToDateTime() throws PageException { 269 throw new ExpressionException("Can't cast Complex Object Type Array to a Date"); 270 } 271 272 @Override 273 public DateTime castToDateTime(DateTime defaultValue) { 274 return defaultValue; 275 } 276 277 @Override 278 public int compareTo(boolean b) throws PageException { 279 throw new ExpressionException("can't compare Complex Object Type Array with a boolean value"); 280 } 281 282 @Override 283 public int compareTo(DateTime dt) throws PageException { 284 throw new ExpressionException("can't compare Complex Object Type Array with a DateTime Object"); 285 } 286 287 @Override 288 public int compareTo(double d) throws PageException { 289 throw new ExpressionException("can't compare Complex Object Type Array with a numeric value"); 290 } 291 292 @Override 293 public int compareTo(String str) throws PageException { 294 throw new ExpressionException("can't compare Complex Object Type Array with a String"); 295 } 296 297 @Override 298 public List toList() { 299 return this; 300 } 301 302 @Override 303 public Iterator<Object> valueIterator() { 304 return iterator(); 305 } 306 307 @Override 308 public Object get(PageContext pc, Key key, Object defaultValue) { 309 return get(key, defaultValue); 310 } 311 312 @Override 313 public Object get(PageContext pc, Key key) throws PageException { 314 return get(key); 315 } 316 317 @Override 318 public Object set(PageContext pc, Key propertyName, Object value) throws PageException { 319 return set(propertyName, value); 320 } 321 322 @Override 323 public Object setEL(PageContext pc, Key propertyName, Object value) { 324 return setEL(propertyName, value); 325 } 326 327 @Override 328 public Object call(PageContext pc, Key methodName, Object[] args) throws PageException { 329 return MemberUtil.call(pc, this, methodName, args, CFTypes.TYPE_ARRAY, "array"); 330 } 331 332 @Override 333 public Object callWithNamedValues(PageContext pc, Key methodName, Struct args) throws PageException { 334 return MemberUtil.callWithNamedValues(pc,this,methodName,args, CFTypes.TYPE_ARRAY, "array"); 335 } 336 337 @Override 338 public java.util.Iterator<Object> getIterator() { 339 return valueIterator(); 340 } 341 342 @Override 343 public synchronized void sort(String sortType, String sortOrder) throws PageException { 344 if(getDimension()>1) 345 throw new ExpressionException("only 1 dimensional arrays can be sorted"); 346 sort(ArrayUtil.toComparator(null, sortType, sortOrder,false)); 347 } 348 349 @Override 350 public boolean equals(Object obj){ 351 if(!(obj instanceof Collection)) return false; 352 return CollectionUtil.equals(this,(Collection)obj); 353 } 354}