1 21 package com.db4o; 22 23 import com.db4o.config.*; 24 import com.db4o.foundation.*; 25 import com.db4o.inside.callbacks.Callbacks; 26 import com.db4o.inside.marshall.*; 27 import com.db4o.inside.query.*; 28 import com.db4o.query.*; 29 import com.db4o.reflect.*; 30 import com.db4o.types.*; 31 32 43 public abstract class QQueryBase implements Unversioned { 44 45 private static final transient IDGenerator i_orderingGenerator = new IDGenerator(); 46 47 transient Transaction i_trans; 48 49 public Collection4 i_constraints = new Collection4(); 50 51 public QQuery i_parent; 52 53 public String i_field; 54 55 private transient QueryEvaluationMode _evaluationMode; 56 57 public int _evaluationModeAsInt; 58 59 public QueryComparator _comparator; 60 61 private transient final QQuery _this; 62 63 protected QQueryBase() { 64 _this = cast(this); 66 } 67 68 protected QQueryBase(Transaction a_trans, QQuery a_parent, String a_field) { 69 _this = cast(this); 70 i_trans = a_trans; 71 i_parent = a_parent; 72 i_field = a_field; 73 } 74 75 void addConstraint(QCon a_constraint) { 76 i_constraints.add(a_constraint); 77 } 78 79 private void addConstraint(Collection4 col, Object obj) { 80 if(attachToExistingConstraints(col, obj, true)){ 81 return; 82 } 83 if(attachToExistingConstraints(col, obj, false)){ 84 return; 85 } 86 QConObject newConstraint = new QConObject(i_trans, null, null, obj); 87 addConstraint(newConstraint); 88 col.add(newConstraint); 89 } 90 91 private boolean attachToExistingConstraints(Collection4 col, Object obj, boolean onlyForPaths) { 92 boolean found = false; 93 Iterator4 j = iterateConstraints(); 94 while (j.moveNext()) { 95 QCon existingConstraint = (QCon)j.current(); 96 boolean[] removeExisting = { false }; 97 if(! onlyForPaths || (existingConstraint instanceof QConPath) ){ 98 QCon newConstraint = existingConstraint.shareParent(obj, removeExisting); 99 if (newConstraint != null) { 100 addConstraint(newConstraint); 101 col.add(newConstraint); 102 if (removeExisting[0]) { 103 removeConstraint(existingConstraint); 104 } 105 found = true; 106 if(! onlyForPaths){ 107 return true; 108 } 109 } 110 } 111 } 112 return found; 113 } 114 115 119 public Constraint constrain(Object example) { 120 synchronized (streamLock()) { 121 example = Platform4.getClassForType(example); 122 123 ReflectClass claxx = reflectClassForClass(example); 124 if (claxx != null) { 125 return addClassConstraint(claxx); 126 } 127 128 QConEvaluation eval = Platform4.evaluationCreate(i_trans, example); 129 if (eval != null) { 130 return addEvaluationToAllConstraints(eval); 131 } 132 133 Collection4 constraints = new Collection4(); 134 addConstraint(constraints, example); 135 return toConstraint(constraints); 136 } 137 } 138 139 private Constraint addEvaluationToAllConstraints(QConEvaluation eval) { 140 Iterator4 i = iterateConstraints(); 141 while (i.moveNext()) { 142 ((QCon)i.current()).addConstraint(eval); 143 } 144 return null; 146 } 147 148 private Constraint addClassConstraint(ReflectClass claxx) { 149 if(claxx.equals(stream().i_handlers.ICLASS_OBJECT)){ 150 return null; 152 } 153 154 Collection4 col = new Collection4(); 155 if (claxx.isInterface()) { 156 return addInterfaceConstraint(claxx); 157 } 158 159 Iterator4 constraintsIterator = iterateConstraints(); 160 while (constraintsIterator.moveNext()) { 161 QCon existingConstraint = (QConObject)constraintsIterator.current(); 162 boolean[] removeExisting = { false }; 163 QCon newConstraint = 164 existingConstraint.shareParentForClass(claxx, removeExisting); 165 if (newConstraint != null) { 166 addConstraint(newConstraint); 167 col.add(newConstraint); 168 if (removeExisting[0]) { 169 removeConstraint(existingConstraint); 170 } 171 } 172 } 173 if (col.size() == 0) { 174 QConClass qcc = new QConClass(i_trans, null, null, claxx); 175 addConstraint(qcc); 176 return qcc; 177 } 178 179 return toConstraint(col); 180 } 181 182 private Constraint addInterfaceConstraint(ReflectClass claxx) { 183 Collection4 classes = stream().classCollection().forInterface(claxx); 184 if (classes.size() == 0) { 185 QConClass qcc = new QConClass(i_trans, null, null, claxx); 186 addConstraint(qcc); 187 return qcc; 188 } 189 Iterator4 i = classes.iterator(); 190 Constraint constr = null; 191 while (i.moveNext()) { 192 YapClass yapClass = (YapClass)i.current(); 193 ReflectClass yapClassClaxx = yapClass.classReflector(); 194 if(yapClassClaxx != null){ 195 if(! yapClassClaxx.isInterface()){ 196 if(constr == null){ 197 constr = constrain(yapClassClaxx); 198 }else{ 199 constr = constr.or(constrain(yapClass.classReflector())); 200 } 201 } 202 } 203 204 } 205 return constr; 206 } 207 208 private ReflectClass reflectClassForClass(Object example) { 209 if(example instanceof ReflectClass){ 210 return (ReflectClass)example; 211 } 212 if(example instanceof Class ) { 213 return i_trans.reflector().forClass((Class )example); 214 } 215 return null; 216 } 217 218 public Constraints constraints() { 219 synchronized (streamLock()) { 220 Constraint[] constraints = new Constraint[i_constraints.size()]; 221 i_constraints.toArray(constraints); 222 return new QConstraints(i_trans, constraints); 223 } 224 } 225 226 public Query descend(final String a_field) { 227 synchronized (streamLock()) { 228 final QQuery query = new QQuery(i_trans, _this, a_field); 229 int[] run = { 1 }; 230 if (!descend1(query, a_field, run)) { 231 232 236 if (run[0] == 1) { 237 run[0] = 2; 238 if (!descend1(query, a_field, run)) { 239 return null; 240 } 241 } 242 } 243 return query; 244 } 245 } 246 247 private boolean descend1(final QQuery query, final String a_field, int[] run) { 248 final boolean[] foundClass = { false }; 249 if (run[0] == 2 || i_constraints.size() == 0) { 250 251 256 run[0] = 0; 258 final boolean[] anyClassCollected = { false }; 259 260 stream().classCollection().attachQueryNode(a_field, new Visitor4() { 261 262 public void visit(Object obj) { 263 264 Object [] pair = ((Object []) obj); 265 YapClass parentYc = (YapClass)pair[0]; 266 YapField yf = (YapField)pair[1]; 267 YapClass childYc = yf.getFieldYapClass(stream()); 268 269 boolean take = true; 270 271 if (childYc instanceof YapClassAny) { 272 if (anyClassCollected[0]) { 273 take = false; 274 } else { 275 anyClassCollected[0] = true; 276 } 277 } 278 279 if (take) { 280 281 QConClass qcc = 282 new QConClass( 283 i_trans, 284 null, 285 yf.qField(i_trans), 286 parentYc.classReflector()); 287 addConstraint(qcc); 288 } 289 290 } 291 292 }); 293 294 } 295 Iterator4 i = iterateConstraints(); 296 while (i.moveNext()) { 297 if (((QCon)i.current()).attach(query, a_field)) { 298 foundClass[0] = true; 299 } 300 } 301 return foundClass[0]; 302 } 303 304 public ObjectSet execute() { 305 Callbacks callbacks = stream().callbacks(); 306 callbacks.onQueryStarted(cast(this)); 307 QueryResult qresult = getQueryResult(); 308 callbacks.onQueryFinished(cast(this)); 309 return new ObjectSetFacade(qresult); 310 } 311 312 public QueryResult getQueryResult() { 313 synchronized (streamLock()) { 314 if(i_constraints.size() == 0){ 315 return stream().getAll(i_trans); 316 } 317 QueryResult result = classOnlyQuery(); 318 if(result != null) { 319 return result; 320 } 321 return stream().executeQuery(_this); 322 } 323 } 324 325 protected YapStream stream() { 326 return i_trans.stream(); 327 } 328 329 private QueryResult classOnlyQuery() { 330 331 if(i_constraints.size()!=1||_comparator!=null) { 332 return null; 333 } 334 Constraint constr=singleConstraint(); 335 if(constr.getClass()!=QConClass.class) { 336 return null; 337 } 338 QConClass clazzconstr=(QConClass)constr; 339 YapClass clazz=clazzconstr.i_yapClass; 340 if(clazz==null) { 341 return null; 342 } 343 if(clazzconstr.hasChildren() || clazz.isArray()) { 344 return null; 345 } 346 347 QueryResult queryResult = stream().classOnlyQuery(i_trans, clazz); 348 if(queryResult == null){ 349 return null; 350 } 351 sort(queryResult); 352 353 return queryResult; 354 355 } 356 357 private Constraint singleConstraint() { 358 return (Constraint)i_constraints.singleElement(); 359 } 360 361 public static class CreateCandidateCollectionResult { 362 public final boolean checkDuplicates; 363 public final boolean topLevel; 364 public final List4 candidateCollection; 365 366 public CreateCandidateCollectionResult(List4 candidateCollection_, boolean checkDuplicates_, boolean topLevel_) { 367 candidateCollection = candidateCollection_; 368 topLevel = topLevel_; 369 checkDuplicates = checkDuplicates_; 370 } 371 } 372 373 public Iterator4 executeSnapshot(){ 374 375 final CreateCandidateCollectionResult r = createCandidateCollection(); 376 377 final Collection4 executionPath = executionPath(r); 378 379 Iterator4 candidatesIterator = new Iterator4Impl(r.candidateCollection); 380 381 Collection4 snapshots = new Collection4(); 382 while(candidatesIterator.moveNext()){ 383 QCandidates candidates = (QCandidates) candidatesIterator.current(); 384 snapshots.add( candidates.executeSnapshot(executionPath)); 385 } 386 387 Iterator4 snapshotsIterator = snapshots.iterator(); 388 final CompositeIterator4 resultingIDs = new CompositeIterator4(snapshotsIterator); 389 390 if(!r.checkDuplicates){ 391 return resultingIDs; 392 } 393 394 return checkDuplicates(resultingIDs); 395 } 396 397 public Iterator4 executeLazy(){ 398 399 final CreateCandidateCollectionResult r = createCandidateCollection(); 400 401 final Collection4 executionPath = executionPath(r); 402 403 Iterator4 candidateCollection = new Iterator4Impl(r.candidateCollection); 404 405 MappingIterator executeCandidates = new MappingIterator(candidateCollection){ 406 protected Object map(Object current) { 407 return ((QCandidates)current).executeLazy(executionPath); 408 } 409 }; 410 411 CompositeIterator4 resultingIDs = new CompositeIterator4(executeCandidates); 412 413 if(!r.checkDuplicates){ 414 return resultingIDs; 415 } 416 417 return checkDuplicates(resultingIDs); 418 } 419 420 private MappingIterator checkDuplicates(CompositeIterator4 executeAllCandidates) { 421 return new MappingIterator(executeAllCandidates) { 422 private TreeInt ids = new TreeInt(0); 423 protected Object map(Object current) { 424 int id = ((Integer )current).intValue(); 425 if(ids.find(id) != null){ 426 return MappingIterator.SKIP; 427 } 428 ids = (TreeInt)ids.add(new TreeInt(id)); 429 return current; 430 } 431 432 }; 433 } 434 435 private Collection4 executionPath(final CreateCandidateCollectionResult r) { 436 return r.topLevel ? null : fieldPathFromTop(); 437 } 438 439 public void executeLocal(final IdListQueryResult result) { 440 441 CreateCandidateCollectionResult r = createCandidateCollection(); 442 443 boolean checkDuplicates = r.checkDuplicates; 444 boolean topLevel = r.topLevel; 445 List4 candidateCollection = r.candidateCollection; 446 447 if (Debug.queries) { 448 logConstraints(); 449 } 450 451 if (candidateCollection != null) { 452 453 final Collection4 executionPath = topLevel ? null : fieldPathFromTop(); 454 455 Iterator4 i = new Iterator4Impl(candidateCollection); 456 while (i.moveNext()) { 457 ((QCandidates)i.current()).execute(); 458 } 459 460 if (candidateCollection._next != null) { 461 checkDuplicates = true; 462 } 463 464 if (checkDuplicates) { 465 result.checkDuplicates(); 466 } 467 468 final YapStream stream = stream(); 469 i = new Iterator4Impl(candidateCollection); 470 while (i.moveNext()) { 471 QCandidates candidates = (QCandidates)i.current(); 472 if (topLevel) { 473 candidates.traverse(result); 474 } else { 475 candidates.traverse(new Visitor4() { 476 public void visit(Object a_object) { 477 QCandidate candidate = (QCandidate)a_object; 478 if (candidate.include()) { 479 TreeInt ids = new TreeInt(candidate._key); 480 final TreeInt[] idsNew = new TreeInt[1]; 481 Iterator4 itPath = executionPath.iterator(); 482 while (itPath.moveNext()) { 483 idsNew[0] = null; 484 final String fieldName = (String ) (itPath.current()); 485 if (ids != null) { 486 ids.traverse(new Visitor4() { 487 public void visit(Object treeInt) { 488 int id = ((TreeInt)treeInt)._key; 489 YapWriter reader = 490 stream.readWriterByID(i_trans, id); 491 if (reader != null) { 492 ObjectHeader oh = new ObjectHeader(stream, reader); 493 idsNew[0] = oh.yapClass().collectFieldIDs( 494 oh._marshallerFamily, 495 oh._headerAttributes, 496 idsNew[0], 497 reader, 498 fieldName); 499 } 500 } 501 }); 502 } 503 ids = idsNew[0]; 504 } 505 if(ids != null){ 506 ids.traverse(new Visitor4() { 507 public void visit(Object treeInt) { 508 result.addKeyCheckDuplicates(((TreeInt)treeInt)._key); 509 } 510 }); 511 } 512 } 513 } 514 }); 515 } 516 } 517 } 518 sort(result); 519 } 521 522 private Collection4 fieldPathFromTop(){ 523 QQueryBase q = this; 524 final Collection4 fieldPath = new Collection4(); 525 while (q.i_parent != null) { 526 fieldPath.prepend(q.i_field); 527 q = q.i_parent; 528 } 529 return fieldPath; 530 } 531 532 private void logConstraints() { 533 if (Debug.queries) { 534 Iterator4 i = iterateConstraints(); 535 while (i.moveNext()) { 536 ((QCon)i.current()).log(""); 537 } 538 } 539 } 540 541 public CreateCandidateCollectionResult createCandidateCollection() { 542 boolean checkDuplicates = false; 543 boolean topLevel = true; 544 List4 candidateCollection = null; 545 Iterator4 i = iterateConstraints(); 546 while (i.moveNext()) { 547 QCon qcon = (QCon)i.current(); 548 QCon old = qcon; 549 qcon = qcon.getRoot(); 550 if (qcon != old) { 551 checkDuplicates = true; 552 topLevel = false; 553 } 554 YapClass yc = qcon.getYapClass(); 555 if (yc == null) { 556 break; 557 } 558 candidateCollection = addConstraintToCandidateCollection(candidateCollection, qcon); 559 } 560 return new CreateCandidateCollectionResult(candidateCollection, checkDuplicates, topLevel); 561 } 562 563 private List4 addConstraintToCandidateCollection(List4 candidateCollection, QCon qcon) { 564 565 if (candidateCollection != null) { 566 if (tryToAddToExistingCandidate(candidateCollection, qcon)) { 567 return candidateCollection; 568 } 569 } 570 571 QCandidates candidates = new QCandidates(i_trans, qcon.getYapClass(), null); 572 candidates.addConstraint(qcon); 573 return new List4(candidateCollection, candidates); 574 } 575 576 private boolean tryToAddToExistingCandidate(List4 candidateCollection, QCon qcon) { 577 Iterator4 j = new Iterator4Impl(candidateCollection); 578 while (j.moveNext()) { 579 QCandidates candidates = (QCandidates)j.current(); 580 if (candidates.tryAddConstraint(qcon)) { 581 return true; 582 } 583 } 584 return false; 585 } 586 587 public final Transaction getTransaction() { 588 return i_trans; 589 } 590 591 Iterator4 iterateConstraints(){ 592 return new Collection4(i_constraints).iterator(); 596 } 597 598 public Query orderAscending() { 599 synchronized (streamLock()) { 600 setOrdering(i_orderingGenerator.next()); 601 return _this; 602 } 603 } 604 605 public Query orderDescending() { 606 synchronized (streamLock()) { 607 setOrdering(-i_orderingGenerator.next()); 608 return _this; 609 } 610 } 611 612 private void setOrdering(final int ordering) { 613 Iterator4 i = iterateConstraints(); 614 while (i.moveNext()) { 615 ((QCon)i.current()).setOrdering(ordering); 616 } 617 } 618 619 public void marshall() { 620 _evaluationModeAsInt = _evaluationMode.asInt(); 621 Iterator4 i = iterateConstraints(); 622 while (i.moveNext()) { 623 ((QCon)i.current()).getRoot().marshall(); 624 } 625 } 626 627 public void unmarshall(final Transaction a_trans) { 628 _evaluationMode = QueryEvaluationMode.fromInt(_evaluationModeAsInt); 629 i_trans = a_trans; 630 Iterator4 i = iterateConstraints(); 631 while (i.moveNext()) { 632 ((QCon)i.current()).unmarshall(a_trans); 633 } 634 } 635 636 void removeConstraint(QCon a_constraint) { 637 i_constraints.remove(a_constraint); 638 } 639 640 Constraint toConstraint(final Collection4 constraints) { 641 if (constraints.size() == 1) { 642 return (Constraint) constraints.singleElement(); 643 } else if (constraints.size() > 0) { 644 Constraint[] constraintArray = new Constraint[constraints.size()]; 645 constraints.toArray(constraintArray); 646 return new QConstraints(i_trans, constraintArray); 647 } 648 return null; 649 } 650 651 protected Object streamLock() { 652 return stream().i_lock; 653 } 654 655 public Query sortBy(QueryComparator comparator) { 656 _comparator=comparator; 657 return _this; 658 } 659 660 private void sort(QueryResult result) { 661 if(_comparator!=null) { 662 result.sort(_comparator); 663 } 664 } 665 666 private static QQuery cast(QQueryBase obj) { 668 return (QQuery)obj; 669 } 670 671 public boolean requiresSort() { 672 if (_comparator != null){ 673 return true; 674 } 675 Iterator4 i = iterateConstraints(); 676 while(i.moveNext()){ 677 QCon qCon = (QCon) i.current(); 678 if(qCon.requiresSort()){ 679 return true; 680 } 681 } 682 return false; 683 } 684 685 public QueryComparator comparator() { 686 return _comparator; 687 } 688 689 public QueryEvaluationMode evaluationMode(){ 690 return _evaluationMode; 691 } 692 693 public void evaluationMode(QueryEvaluationMode mode){ 694 _evaluationMode = mode; 695 } 696 697 } 698 | Popular Tags |