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