1 15 package org.josql.expressions; 16 17 import java.util.Map ; 18 import java.util.List ; 19 import java.util.ArrayList ; 20 import java.util.Collection ; 21 import java.util.Iterator ; 22 23 import com.gentlyweb.utils.Getter; 24 25 import org.josql.Query; 26 import org.josql.QueryResults; 27 import org.josql.QueryExecutionException; 28 import org.josql.QueryParseException; 29 30 import org.josql.internal.Utilities; 31 32 import org.josql.events.*; 33 34 public class SubQueryExpression extends ValueExpression implements BindVariableChangedListener, 35 SaveValueChangedListener 36 { 37 38 private Query q = null; 39 private boolean inited = false; 40 private String acc = null; 41 private Getter get = null; 42 private boolean nullQuery = false; 43 44 public SubQueryExpression (Query q) 45 { 46 47 this.q = q; 48 49 this.q.addBindVariableChangedListener (this); 50 this.q.addSaveValueChangedListener (this); 51 52 } 53 54 public void bindVariableChanged (BindVariableChangedEvent ev) 55 { 56 57 if (this.q.getFrom () instanceof BindVariable) 58 { 59 60 BindVariable bv = (BindVariable) this.q.getFrom (); 61 62 if (bv.getName ().equalsIgnoreCase (ev.getName ())) 63 { 64 65 this.inited = false; 66 67 } 68 69 } 70 71 } 72 73 public void saveValueChanged (SaveValueChangedEvent ev) 74 { 75 76 if (this.q.getFrom () instanceof SaveValue) 77 { 78 79 SaveValue sv = (SaveValue) this.q.getFrom (); 80 81 if (sv.getName ().equalsIgnoreCase (ev.getName ())) 82 { 83 84 this.inited = false; 85 86 } 87 88 } 89 90 } 91 92 public Getter getGetter () 93 { 94 95 return this.get; 96 97 } 98 99 public void setAccessor (String acc) 100 { 101 102 this.acc = acc; 103 104 } 105 106 public String getAccessor () 107 { 108 109 return this.acc; 110 111 } 112 113 public Query getQuery () 114 { 115 116 return this.q; 117 118 } 119 120 public boolean hasFixedResult (Query q) 121 { 122 123 return false; 124 125 } 126 127 public Class getExpectedReturnType (Query q) 128 throws QueryParseException 129 { 130 131 if (this.get != null) 132 { 133 134 return this.get.getType (); 135 136 } 137 138 return List .class; 139 140 } 141 142 public void init (Query q) 143 throws QueryParseException 144 { 145 146 if (this.acc != null) 148 { 149 150 try 151 { 152 153 this.get = new Getter (this.acc, 154 ArrayList .class); 155 156 } catch (Exception e) { 157 158 throw new QueryParseException ("Sub-query: " + 159 this + 160 " has accessor: " + 161 this.acc + 162 " however no valid accessor has been found in return type: " + 163 ArrayList .class.getName (), 164 e); 165 166 } 167 168 } 169 170 } 171 172 public boolean isTrue (Object o, 173 Query q) 174 throws QueryExecutionException 175 { 176 177 List l = (List ) this.getValue (o, 178 q); 179 180 return l.size () > 0; 181 182 } 183 184 private void innerInit (Object o, 185 Query q) 186 throws QueryExecutionException 187 { 188 189 Object obj = null; 190 191 Expression from = this.q.getFrom (); 192 193 if (from instanceof ConstantExpression) 194 { 195 196 String g = (String ) from.getValue (null, 198 this.q); 199 200 if (!g.equalsIgnoreCase ("null")) 202 { 203 204 Accessor acc = new Accessor (); 205 206 acc.setAccessor (g); 207 208 this.q.setFrom (acc); 209 210 try 211 { 212 213 acc.init (q); 215 216 } catch (Exception e) { 217 218 throw new QueryExecutionException ("Unable to init accessor: " + 219 g + 220 " from class: " + 221 o.getClass () + 222 " for FROM clause, for sub-query: \"" + 223 this.q + 224 "\"", 225 e); 226 227 } 228 229 obj = this.q.getFrom ().getValue (o, 231 this.q); 232 233 } else { 234 235 List l = new ArrayList (); 237 l.add (new Object ()); 238 239 obj = l; 240 241 this.nullQuery = true; 242 243 } 244 245 } 246 247 if (from instanceof Accessor) 248 { 249 250 obj = this.q.getFrom ().getValue (o, 252 this.q); 253 254 } 255 256 if (from instanceof Function) 257 { 258 259 try 260 { 261 262 from.init (this.q); 263 264 } catch (Exception e) { 265 266 throw new QueryExecutionException ("Unable to init FROM clause: " + 267 from + 268 " for sub-query: " + 269 this.q, 270 e); 271 272 } 273 274 obj = this.q.getFrom ().getValue (o, 277 q); 278 279 } 280 281 if (from instanceof SaveValue) 282 { 283 284 obj = from.getValue (o, 285 q.getTopLevelQuery ()); 286 287 } 288 289 if (from instanceof BindVariable) 290 { 291 292 try 294 { 295 296 from.init (q.getTopLevelQuery ()); 297 298 } catch (Exception e) { 299 300 throw new QueryExecutionException ("Unable to init FROM clause: " + 301 from + 302 " for sub-query: " + 303 this.q, 304 e); 305 306 } 307 308 obj = from.getValue (o, 309 q.getTopLevelQuery ()); 310 311 } 312 313 if (obj == null) 314 { 315 316 return; 317 318 } 319 320 if (!(obj instanceof Collection )) 322 { 323 324 throw new QueryExecutionException ("Expected FROM clause: " + 325 this.q.getFrom () + 326 " for sub-query: " + 327 this.q + 328 " to evaluate to an instance of: " + 329 Collection .class.getName () + 330 ", instead evaluates to: " + 331 obj.getClass ().getName () + 332 " using from expression: " + 333 from); 334 335 } 336 337 Collection col = (Collection ) obj; 338 339 Iterator iter = col.iterator (); 341 342 if (!iter.hasNext ()) 343 { 344 345 return; 346 347 } 348 349 Object io = iter.next (); 350 351 if (io == null) 353 { 354 355 while (iter.hasNext ()) 358 { 359 360 io = iter.next (); 361 362 if (io != null) 363 { 364 365 break; 366 367 } 368 369 } 370 371 } 372 373 if (io == null) 374 { 375 376 return; 378 379 } 380 381 this.q.setFromObjectClass (io.getClass ()); 382 383 try 384 { 385 386 this.q.init (); 387 388 } catch (Exception e) { 389 390 throw new QueryExecutionException ("Unable to init sub-query: " + 391 this.q + 392 " with class: " + 393 io.getClass ().getName (), 394 e); 395 396 } 397 398 this.inited = true; 399 400 } 401 402 private List innerGetValue (Object o, 403 Query q) 404 throws QueryExecutionException 405 { 406 407 if (this.nullQuery) 408 { 409 410 return Query.nullQueryList; 411 412 } 413 414 Object obj = null; 415 416 try 417 { 418 419 obj = this.q.getFrom ().getValue (o, 420 this.q.getTopLevelQuery ()); 421 422 } catch (Exception e) { 423 424 throw new QueryExecutionException ("Unable to evaluate FROM clause accessor: " + 425 this.q.getFrom () + 426 " for sub-query: " + 427 this.q, 428 e); 429 430 } 431 432 if (obj == null) 433 { 434 435 return new ArrayList (); 436 437 } 438 439 if (!(obj instanceof Collection )) 440 { 441 442 throw new QueryExecutionException ("Evaluation of FROM clause for sub-query: " + 443 this.q + 444 " returns an instance of: " + 445 obj.getClass ().getName () + 446 " however only sub-classes of: " + 447 Collection .class.getName () + 448 " are supported."); 449 450 } 451 452 List l = null; 453 454 if (obj instanceof List ) 456 { 457 458 l = (List ) obj; 459 460 } else { 461 462 l = new ArrayList ((Collection ) obj); 463 464 } 465 466 return l; 467 468 } 469 470 public Object evaluate (Object o, 471 Query q) 472 throws QueryExecutionException 473 { 474 475 this.q.setParent (q); 476 477 if (!this.inited) 478 { 479 480 this.innerInit (o, 481 q); 482 483 } 484 485 if (this.inited) 486 { 487 488 List l = this.innerGetValue (o, 489 q); 490 491 QueryResults qr = this.q.execute (l); 492 493 if (this.get != null) 494 { 495 496 try 497 { 498 499 return this.get.getValue (qr.getResults ()); 500 501 } catch (Exception e) { 502 503 throw new QueryExecutionException ("Unable to get value for accessor: " + 504 this.acc + 505 " from return type: " + 506 ArrayList .class.getName () + 507 " after execution of sub-query: " + 508 this, 509 e); 510 511 } 512 513 } 514 515 return qr.getResults (); 516 517 } 518 519 return new ArrayList (); 520 521 } 522 523 public String toString () 524 { 525 526 return "(" + this.q.toString () + ")"; 527 528 } 529 530 } 531
| Popular Tags
|