001 package railo.runtime.type.scope; 002 003 import java.util.ArrayList; 004 import java.util.Iterator; 005 import java.util.LinkedHashMap; 006 import java.util.List; 007 import java.util.Map; 008 import java.util.Set; 009 010 import railo.runtime.PageContext; 011 import railo.runtime.dump.DumpData; 012 import railo.runtime.dump.DumpProperties; 013 import railo.runtime.dump.DumpTable; 014 import railo.runtime.dump.DumpTablePro; 015 import railo.runtime.dump.DumpUtil; 016 import railo.runtime.dump.SimpleDumpData; 017 import railo.runtime.exp.ExpressionException; 018 import railo.runtime.exp.PageException; 019 import railo.runtime.op.Caster; 020 import railo.runtime.op.Decision; 021 import railo.runtime.type.Array; 022 import railo.runtime.type.ArrayImpl; 023 import railo.runtime.type.Collection; 024 import railo.runtime.type.KeyImpl; 025 import railo.runtime.type.Struct; 026 import railo.runtime.type.StructImpl; 027 import railo.runtime.type.wrap.ArrayAsList; 028 029 /** 030 * implementation of the argument scope 031 */ 032 public final class ArgumentImpl extends ScopeSupport implements ArgumentPro { 033 034 private boolean bind; 035 private Set functionArgumentNames; 036 //private boolean supportFunctionArguments; 037 038 /** 039 * constructor of the class 040 */ 041 public ArgumentImpl() { 042 super("arguments",SCOPE_ARGUMENTS,Struct.TYPE_LINKED); 043 //this(true); 044 } 045 046 047 /** 048 * @see railo.runtime.type.scope.ScopeSupport#release() 049 */ 050 public void release() { 051 functionArgumentNames=null; 052 super.release(); 053 } 054 055 056 057 /** 058 * @see railo.runtime.type.scope.Argument#setBind(boolean) 059 */ 060 public void setBind(boolean bind) { 061 this.bind=bind; 062 } 063 064 /** 065 * @see railo.runtime.type.scope.Argument#isBind() 066 */ 067 public boolean isBind() { 068 return this.bind; 069 } 070 071 public Object getFunctionArgument(String key, Object defaultValue) { 072 return getFunctionArgument(KeyImpl.getInstance(key), defaultValue); 073 } 074 075 public Object getFunctionArgument(Collection.Key key, Object defaultValue) { 076 if((functionArgumentNames==null || !functionArgumentNames.contains(key))){ 077 return defaultValue; 078 } 079 return get(key, defaultValue); 080 } 081 082 083 /** 084 * @see railo.runtime.type.scope.ArgumentPro#containsFunctionArgumentKey(railo.runtime.type.Collection.Key) 085 */ 086 public boolean containsFunctionArgumentKey(Key key) { 087 return functionArgumentNames!=null && functionArgumentNames.contains(key); 088 } 089 090 091 092 /** 093 * 094 * @see railo.runtime.type.StructImpl#get(railo.runtime.type.Collection.Key, java.lang.Object) 095 */ 096 public Object get(Collection.Key key, Object defaultValue) { 097 Object o=super.get(key,null); 098 if(o!=null)return o; 099 100 o=get(Caster.toIntValue(key.getString(),-1),null); 101 if(o!=null)return o; 102 if(super.containsKey(key)) return null;// that is only for compatibility to neo 103 return defaultValue; 104 } 105 106 107 /** 108 * 109 * @see railo.runtime.type.StructImpl#get(railo.runtime.type.Collection.Key) 110 */ 111 public Object get(Collection.Key key) throws ExpressionException { 112 Object o=super.get(key,null); 113 if(o!=null)return o; 114 115 o=get(Caster.toIntValue(key.getString(),-1),null); 116 if(o!=null)return o; 117 if(super.containsKey(key)) return null;// that is only for compatibility to neo 118 throw new ExpressionException("key ["+key.getString()+"] doesn't exist in argument scope"); 119 120 } 121 122 /** 123 * 124 * @see railo.runtime.type.Array#get(int, java.lang.Object) 125 */ 126 public Object get(int intKey, Object defaultValue) { 127 Iterator it = valueIterator();//keyIterator();//getMap().keySet().iterator(); 128 int count=0; 129 Object o; 130 while(it.hasNext()) { 131 o=it.next(); 132 if((++count)==intKey) { 133 return o;//super.get(o.toString(),defaultValue); 134 } 135 } 136 return defaultValue; 137 } 138 139 /** 140 * return a value matching to key 141 * @param intKey 142 * @return value matching key 143 * @throws PageException 144 */ 145 public Object getE(int intKey) throws PageException { 146 Iterator it = valueIterator();//getMap().keySet().iterator(); 147 int count=0; 148 Object o; 149 while(it.hasNext()) { 150 o=it.next(); 151 if((++count)==intKey) { 152 return o;//super.get(o.toString()); 153 } 154 } 155 throw new ExpressionException("invalid index ["+intKey+"] for argument scope"); 156 } 157 158 /** 159 * @see railo.runtime.dump.Dumpable#toDumpData(railo.runtime.PageContext, int) 160 */ 161 public DumpData toDumpData(PageContext pageContext, int maxlevel, DumpProperties dp) { 162 DumpTable htmlBox = new DumpTablePro("struct","#9999ff","#ccccff","#000000"); 163 htmlBox.setTitle("Scope Arguments"); 164 if(size()>10 && dp.getMetainfo())htmlBox.setComment("Entries:"+size()); 165 166 maxlevel--; 167 //Map mapx=getMap(); 168 Iterator it=keyIterator();//mapx.keySet().iterator(); 169 int count=0; 170 Collection.Key key; 171 int maxkeys=dp.getMaxKeys(); 172 int index=0; 173 while(it.hasNext()) { 174 key=KeyImpl.toKey(it.next(), null);//it.next(); 175 176 if(DumpUtil.keyValid(dp, maxlevel,key)){ 177 if(maxkeys<=index++)break; 178 htmlBox.appendRow(3, 179 new SimpleDumpData(key.getString()), 180 new SimpleDumpData(++count), 181 DumpUtil.toDumpData(get(key,null), 182 pageContext,maxlevel,dp)); 183 } 184 } 185 return htmlBox; 186 } 187 188 189 /** 190 * @see railo.runtime.type.Array#getDimension() 191 */ 192 public int getDimension() { 193 return 1; 194 } 195 196 /** 197 * @see railo.runtime.type.Array#setEL(int, java.lang.Object) 198 */ 199 public Object setEL(int intKey, Object value) { 200 int count=0; 201 202 if(intKey>size()) { 203 return setEL(Caster.toString(intKey),value); 204 } 205 //Iterator it = keyIterator(); 206 Key[] keys = keys(); 207 for(int i=0;i<keys.length;i++) { 208 if((++count)==intKey) { 209 return super.setEL(keys[i],value); 210 } 211 } 212 return value; 213 } 214 215 216 /** 217 * @see railo.runtime.type.Array#setE(int, java.lang.Object) 218 */ 219 public Object setE(int intKey, Object value) throws PageException { 220 221 if(intKey>size()) { 222 return set(Caster.toString(intKey),value); 223 } 224 //Iterator it = keyIterator(); 225 Key[] keys = keys(); 226 for(int i=0;i<keys.length;i++) { 227 if((i+1)==intKey) { 228 return super.set(keys[i],value); 229 } 230 } 231 throw new ExpressionException("invalid index ["+intKey+"] for argument scope"); 232 } 233 234 235 /** 236 * @see railo.runtime.type.Array#intKeys() 237 */ 238 public int[] intKeys() { 239 int[] ints=new int[size()]; 240 for(int i=0;i<ints.length;i++)ints[i]=i+1; 241 return ints; 242 } 243 244 245 /** 246 * @see railo.runtime.type.Array#insert(int, java.lang.Object) 247 */ 248 public boolean insert(int index, Object value) throws ExpressionException { 249 return insert(index, ""+index, value); 250 } 251 252 /** 253 * @see railo.runtime.type.scope.Argument#insert(int, java.lang.String, java.lang.Object) 254 */ 255 public boolean insert(int index, String key, Object value) throws ExpressionException { 256 int len=size(); 257 if(index<1 || index>len) 258 throw new ExpressionException("invalid index to insert a value to argument scope",len==0?"can't insert in a empty argument scope":"valid index goes from 1 to "+(len-1)); 259 260 // remove all upper 261 LinkedHashMap lhm = new LinkedHashMap(); 262 String[] keys=keysAsString(); 263 264 String k; 265 for(int i=1;i<=keys.length;i++) { 266 if(i<index)continue; 267 k=keys[i-1]; 268 lhm.put(k,get(k,null)); 269 removeEL(KeyImpl.getInstance(k)); 270 } 271 272 // set new value 273 setEL(key,value); 274 275 // reset upper values 276 Iterator it = lhm.entrySet().iterator(); 277 Map.Entry entry; 278 while(it.hasNext()) { 279 entry=(Entry) it.next(); 280 setEL(KeyImpl.toKey(entry.getKey()),entry.getValue()); 281 } 282 return true; 283 } 284 285 286 /** 287 * @see railo.runtime.type.Array#append(java.lang.Object) 288 */ 289 public Object append(Object o) throws PageException { 290 return set(Caster.toString(size()+1),o); 291 } 292 293 /** 294 * @see railo.runtime.type.Array#appendEL(java.lang.Object) 295 */ 296 public Object appendEL(Object o) { 297 try { 298 return append(o); 299 } catch (PageException e) { 300 return null; 301 } 302 } 303 304 305 /** 306 * @see railo.runtime.type.Array#prepend(java.lang.Object) 307 */ 308 public Object prepend(Object o) throws PageException { 309 for(int i=size();i>0;i--) { 310 setE(i+1,getE(i)); 311 } 312 setE(1,o); 313 return o; 314 } 315 316 317 /** 318 * @see railo.runtime.type.Array#resize(int) 319 */ 320 public void resize(int to) throws PageException { 321 for(int i=size(); i<to; i++) { 322 append(null); 323 } 324 //throw new ExpressionException("can't resize this array"); 325 } 326 327 328 329 /** 330 * @see railo.runtime.type.Array#sort(java.lang.String, java.lang.String) 331 */ 332 public void sort(String sortType, String sortOrder) throws ExpressionException { 333 // TODO Impl. 334 throw new ExpressionException("can't sort ["+sortType+"-"+sortOrder+"] Argument Scope","not Implemnted Yet"); 335 } 336 337 /** 338 * @see railo.runtime.type.Array#toArray() 339 */ 340 public Object[] toArray() { 341 Iterator it = keyIterator();//getMap().keySet().iterator(); 342 Object[] arr=new Object[size()]; 343 int count=0; 344 345 while(it.hasNext()) { 346 arr[count++]=it.next(); 347 } 348 return arr; 349 } 350 351 public Object setArgument(Object obj) throws PageException { 352 if(obj==this) return obj; 353 354 355 if(Decision.isStruct(obj)) { 356 clear(); // TODO bessere impl. anstelle vererbung wrao auf struct 357 Struct sct=Caster.toStruct(obj); 358 Iterator it = sct.keyIterator(); 359 String key; 360 while(it.hasNext()) { 361 key=it.next().toString(); 362 setEL(key, sct.get(key,null)); 363 } 364 return obj; 365 } 366 throw new ExpressionException("can not overwrite arguments scope"); 367 } 368 369 370 /** 371 * @see railo.runtime.type.Array#toArrayList() 372 */ 373 public ArrayList toArrayList() { 374 ArrayList list = new ArrayList(); 375 Object[] arr = toArray(); 376 for(int i=0;i<arr.length;i++) { 377 list.add(arr[i]); 378 } 379 return list; 380 } 381 382 /** 383 * @see railo.runtime.type.Array#removeE(int) 384 */ 385 public Object removeE(int intKey) throws PageException { 386 Key[] keys = keys(); 387 for(int i=0;i<keys.length;i++) { 388 if((i+1)==intKey) { 389 return super.remove(keys[i]); 390 } 391 } 392 throw new ExpressionException("can't remove argument number ["+intKey+"], argument doesn't exist"); 393 } 394 395 /** 396 * @see railo.runtime.type.Array#removeEL(int) 397 */ 398 public Object removeEL(int intKey) { 399 Key[] keys = keys(); 400 for(int i=0;i<keys.length;i++) { 401 if((i+1)==intKey) { 402 return super.removeEL (keys[i]); 403 } 404 } 405 return null; 406 } 407 408 /** 409 * @see railo.runtime.type.StructImpl#containsKey(railo.runtime.type.Collection.Key) 410 */ 411 public boolean containsKey(Collection.Key key) { 412 return get(key,null)!=null && super.containsKey(key); 413 } 414 415 /** 416 * @see railo.runtime.type.Array#containsKey(int) 417 */ 418 public boolean containsKey(int key) { 419 return get(key,null)!=null; 420 } 421 422 423 424 /** 425 * @see railo.runtime.type.Array#toList() 426 */ 427 public List toList() { 428 return ArrayAsList.toList(this); 429 } 430 431 432 /** 433 * @see railo.runtime.type.StructImpl#duplicate(boolean) 434 */ 435 public Collection duplicate(boolean deepCopy) { 436 ArgumentImpl trg=new ArgumentImpl(); 437 trg.bind=false; 438 trg.functionArgumentNames=functionArgumentNames; 439 //trg.supportFunctionArguments=supportFunctionArguments; 440 copy(this,trg,deepCopy); 441 return trg; 442 } 443 444 public void setFunctionArgumentNames(Set functionArgumentNames) {// future add to interface 445 this.functionArgumentNames=functionArgumentNames; 446 } 447 /* 448 public void setNamedArguments(boolean namedArguments) { 449 this.namedArguments=namedArguments; 450 } 451 public boolean isNamedArguments() { 452 return namedArguments; 453 } 454 */ 455 456 /** 457 * converts a argument scope to a regular struct 458 * @param arg argument scope to convert 459 * @return resulting struct 460 */ 461 public static Struct toStruct(Argument arg) { 462 Struct trg=new StructImpl(); 463 StructImpl.copy(arg, trg, false); 464 return trg; 465 } 466 467 /** 468 * converts a argument scope to a regular array 469 * @param arg argument scope to convert 470 * @return resulting array 471 */ 472 public static Array toArray(Argument arg) { 473 ArrayImpl trg=new ArrayImpl(); 474 int[] keys = arg.intKeys(); 475 for(int i=0;i<keys.length;i++){ 476 trg.setEL(keys[i], 477 arg.get(keys[i],null)); 478 } 479 return trg; 480 } 481 }