1 21 22 package oracle.toplink.essentials.internal.expressions; 24 25 import java.io.*; 26 import java.util.*; 27 import oracle.toplink.essentials.descriptors.FetchGroupManager; 28 import oracle.toplink.essentials.exceptions.*; 29 import oracle.toplink.essentials.expressions.*; 30 import oracle.toplink.essentials.internal.helper.*; 31 import oracle.toplink.essentials.mappings.*; 32 import oracle.toplink.essentials.mappings.foundation.AbstractDirectMapping; 33 import oracle.toplink.essentials.queryframework.*; 34 import oracle.toplink.essentials.querykeys.*; 35 import oracle.toplink.essentials.internal.sessions.AbstractRecord; 36 import oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl; 37 import oracle.toplink.essentials.internal.sessions.AbstractSession; 38 import oracle.toplink.essentials.descriptors.ClassDescriptor; 39 40 44 public class QueryKeyExpression extends ObjectExpression { 45 46 47 protected String name; 48 49 50 protected DatabaseField aliasedField; 51 52 53 protected boolean shouldQueryToManyRelationship; 54 55 56 transient protected QueryKey queryKey; 57 protected boolean hasQueryKey; 58 59 60 transient protected DatabaseMapping mapping; 61 protected boolean hasMapping; 62 63 public QueryKeyExpression() { 64 this.shouldQueryToManyRelationship = false; 65 this.hasQueryKey = true; 66 this.hasMapping = true; 67 } 68 69 public QueryKeyExpression(String aName, Expression base) { 70 super(); 71 name = aName; 72 baseExpression = base; 73 shouldUseOuterJoin = false; 74 shouldQueryToManyRelationship = false; 75 hasQueryKey = true; 76 hasMapping = true; 77 } 78 79 83 public Expression additionalExpressionCriteria() { 84 if (getDescriptor() == null) { 85 return null; 86 } 87 88 Expression criteria = getDescriptor().getQueryManager().getAdditionalJoinExpression(); 89 if (criteria != null) { 90 criteria = getBaseExpression().twist(criteria, this); 91 if (shouldUseOuterJoin() && getSession().getPlatform().shouldPrintOuterJoinInWhereClause()) { 92 criteria.convertToUseOuterJoin(); 93 } 94 } 95 96 if(getSession().getPlatform().shouldPrintOuterJoinInWhereClause()) { 97 if(isUsingOuterJoinForMultitableInheritance()) { 98 Expression childrenCriteria = getDescriptor().getInheritancePolicy().getChildrenJoinExpression(); 99 childrenCriteria = getBaseExpression().twist(childrenCriteria, this); 100 childrenCriteria.convertToUseOuterJoin(); 101 if(criteria == null) { 102 criteria = childrenCriteria; 103 } else { 104 criteria = criteria.and(childrenCriteria); 105 } 106 } 107 } 108 109 return criteria; 110 } 111 112 117 public Map additionalExpressionCriteriaMap() { 118 if (getDescriptor() == null) { 119 return null; 120 } 121 122 HashMap tablesJoinExpressions = new HashMap(); 123 Vector tables = getDescriptor().getTables(); 124 int tablesSize = tables.size(); 126 if(shouldUseOuterJoin()) { 127 for( int i=1; i < tablesSize; i++) { 128 DatabaseTable table = (DatabaseTable)tables.elementAt(i); 129 Expression joinExpression = (Expression)getDescriptor().getQueryManager().getTablesJoinExpressions().get(table); 130 joinExpression = getBaseExpression().twist(joinExpression, this); 131 tablesJoinExpressions.put(table, joinExpression); 132 } 133 } 134 if(isUsingOuterJoinForMultitableInheritance()) { 135 List childrenTables = getDescriptor().getInheritancePolicy().getChildrenTables(); 136 tablesSize = childrenTables.size(); 137 for( int i=0; i < tablesSize; i++) { 138 DatabaseTable table = (DatabaseTable)childrenTables.get(i); 139 Expression joinExpression = (Expression)getDescriptor().getInheritancePolicy().getChildrenTablesJoinExpressions().get(table); 140 joinExpression = getBaseExpression().twist(joinExpression, this); 141 tablesJoinExpressions.put(table, joinExpression); 142 } 143 } 144 145 return tablesJoinExpressions; 146 } 147 148 152 public DatabaseTable aliasForTable(DatabaseTable table) { 153 if (isAttribute() || ((getMapping() != null) && (getMapping().isAggregateObjectMapping() || getMapping().isTransformationMapping()))) { 154 return ((DataExpression)getBaseExpression()).aliasForTable(table); 155 } 156 157 if ((getMapping() != null) && (getMapping().isReferenceMapping() || getMapping().isStructureMapping())) { 159 DatabaseTable alias = getBaseExpression().aliasForTable((DatabaseTable)getMapping().getDescriptor().getTables().firstElement()); 160 alias.setName(alias.getName() + "." + getMapping().getField().getName()); 161 return alias; 162 } 163 164 return super.aliasForTable(table); 165 } 166 167 171 public String descriptionOfNodeType() { 172 return "Query Key"; 173 } 174 175 178 public void doQueryToManyRelationship() { 179 shouldQueryToManyRelationship = true; 180 } 181 182 186 public DatabaseField getAliasedField() { 187 if (aliasedField == null) { 188 initializeAliasedField(); 189 } 190 return aliasedField; 191 192 } 193 194 197 protected DatabaseTable getAliasedTable() { 198 DataExpression base = (DataExpression)getBaseExpression(); 199 200 DatabaseTable alias = base.aliasForTable(getField().getTable()); 201 if (alias == null) { 202 return getField().getTable(); 203 } else { 204 return alias; 205 } 206 } 207 208 212 public ClassDescriptor getContainingDescriptor() { 213 return ((DataExpression)getBaseExpression()).getDescriptor(); 214 } 215 216 219 public DatabaseField getField() { 220 if (!isAttribute()) { 221 return null; 222 } 223 224 return getContainingDescriptor().getObjectBuilder().getFieldForQueryKeyName(getName()); 225 } 226 227 231 public Vector getFields() { 232 if (isAttribute()) { 233 Vector result = new Vector(1); 234 DatabaseField field = getField(); 235 if (field != null) { 236 result.addElement(field); 237 } 238 return result; 239 } else if ((getMapping() != null) && getMapping().isTransformationMapping()) { 240 return getMapping().getFields(); 241 } else { 242 if(isUsingOuterJoinForMultitableInheritance()) { 243 return getDescriptor().getAllFields(); 244 } else { 245 return super.getFields(); 246 } 247 } 248 } 249 250 254 public Object getFieldValue(Object objectValue) { 255 DatabaseMapping mapping = getMapping(); 256 Object fieldValue = objectValue; 257 if ((mapping != null) && (mapping.isDirectToFieldMapping())) { 258 if (objectValue instanceof Vector) { 260 Vector values = (Vector)objectValue; 262 Vector fieldValues = new Vector(values.size()); 263 for (int index = 0; index < values.size(); index++) { 264 fieldValues.addElement(getFieldValue(values.get(index))); 265 } 266 fieldValue = fieldValues; 267 } else { 268 fieldValue = ((AbstractDirectMapping)mapping).getFieldValue(objectValue, getSession()); 269 } 270 } 271 272 return fieldValue; 273 } 274 275 public DatabaseMapping getMapping() { 276 if (!hasMapping) { 277 return null; 278 } 279 280 if (mapping == null) { 281 mapping = super.getMapping(); 282 if (mapping == null) { 283 hasMapping = false; 284 } 285 } 286 return mapping; 287 } 288 289 public DatabaseMapping getMappingFromQueryKey() { 290 QueryKey queryKey = getQueryKeyOrNull(); 291 if ((queryKey == null) || (!(queryKey instanceof DirectQueryKey))) { 292 throw QueryException.cannotConformExpression(); 293 } 294 mapping = queryKey.getDescriptor().getObjectBuilder().getMappingForField(((DirectQueryKey)queryKey).getField()); 295 if (mapping == null) { 296 throw QueryException.cannotConformExpression(); 297 } 298 return mapping; 299 } 300 301 public String getName() { 302 return name; 303 } 304 305 308 public Vector getOwnedTables() { 309 if ((getMapping() != null) && (getMapping().isReferenceMapping() || getMapping().isStructureMapping())) { 310 return null; 311 } 312 313 return super.getOwnedTables(); 314 } 315 316 public QueryKey getQueryKeyOrNull() { 317 if (!hasQueryKey) { 318 return null; 319 } 320 321 if (getContainingDescriptor() == null) { 326 throw QueryException.invalidQueryKeyInExpression(getName()); 327 } 328 if (queryKey == null) { 329 queryKey = getContainingDescriptor().getQueryKeyNamed(getName()); 330 if (queryKey == null) { 331 hasQueryKey = false; 332 } 333 } 334 return queryKey; 335 336 } 337 338 342 protected void initializeAliasedField() { 343 DatabaseField tempField = (DatabaseField)getField().clone(); 344 DatabaseTable aliasedTable = getAliasedTable(); 345 346 aliasedField = tempField; 353 aliasedField.setTable(aliasedTable); 354 } 356 357 360 public boolean isAttribute() { 361 if (getSession() == null) { return false; 363 } 364 365 try { 366 QueryKey queryKey = getQueryKeyOrNull(); 367 if (queryKey != null) { 368 return queryKey.isDirectQueryKey(); 369 } 370 371 DatabaseMapping mapping = getMapping(); 372 if (mapping != null) { 373 if (mapping.isVariableOneToOneMapping()) { 374 throw QueryException.cannotQueryAcrossAVariableOneToOneMapping(mapping, mapping.getDescriptor()); 375 } else { 376 return mapping.isDirectToFieldMapping(); 377 } 378 } 379 } catch (QueryException e) { 380 throw e; } 382 return false; 383 } 384 385 public boolean isQueryKeyExpression() { 386 return true; 387 } 388 389 394 public Expression mappingCriteria() { 395 Expression selectionCriteria; 396 397 if (getQueryKeyOrNull() == null) { 399 if ((getMapping() == null) || (!getMapping().isForeignReferenceMapping())) { 400 return null; 401 } else { 402 selectionCriteria = ((ForeignReferenceMapping)getMapping()).getJoinCriteria(this); 404 } 405 } else { 406 if (!getQueryKeyOrNull().isForeignReferenceQueryKey()) { 407 return null; 408 } else { 409 selectionCriteria = ((ForeignReferenceQueryKey)getQueryKeyOrNull()).getJoinCriteria(); 410 selectionCriteria = getBaseExpression().twist(selectionCriteria, this); 411 } 412 } 413 414 if (shouldUseOuterJoin() && getSession().getPlatform().shouldPrintOuterJoinInWhereClause()) { 415 selectionCriteria = selectionCriteria.convertToUseOuterJoin(); 416 } 417 418 return selectionCriteria; 419 } 420 421 426 public Expression normalize(ExpressionNormalizer normalizer) { 427 return normalize(normalizer, null); 428 } 429 430 436 public Expression normalize(ExpressionNormalizer normalizer, Vector foreignKeyJoinPointer) { 437 if (hasBeenNormalized()) { 438 return this; 439 } 440 super.normalize(normalizer); 441 442 setHasBeenNormalized(true); 443 if ((getMapping() != null) && getMapping().isDirectToXMLTypeMapping()) { 444 normalizer.getStatement().setRequiresAliases(true); 445 } 446 447 if (isAttribute()) { 449 return this; 450 } 451 452 if ((getMapping() != null) && (getMapping().isReferenceMapping() || getMapping().isStructureMapping())) { 454 normalizer.getStatement().setRequiresAliases(true); 455 return this; 456 } 457 458 if (shouldQueryToManyRelationship() && (!normalizer.getStatement().isDistinctComputed()) && (!normalizer.getStatement().isAggregateSelect())) { 460 normalizer.getStatement().useDistinct(); 461 } 462 463 if ((getMapping() != null) && getMapping().isNestedTableMapping()) { 465 if (!shouldQueryToManyRelationship()) { 467 return this; 468 } 469 normalizer.getStatement().dontUseDistinct(); 470 } 471 472 Expression mappingExpression = mappingCriteria(); 473 if (mappingExpression != null) { 474 mappingExpression = mappingExpression.normalize(normalizer); 475 } 476 if (mappingExpression != null) { 477 if (shouldUseOuterJoin() && (getSession().getPlatform().isInformixOuterJoin())) { 480 normalizer.getStatement().getOuterJoinExpressions().addElement(this); 481 normalizer.getStatement().getOuterJoinedMappingCriteria().addElement(mappingExpression); 482 normalizer.addAdditionalExpression(mappingExpression.and(additionalExpressionCriteria())); 483 return this; 484 } else if ((shouldUseOuterJoin() || isUsingOuterJoinForMultitableInheritance()) && (!getSession().getPlatform().shouldPrintOuterJoinInWhereClause())) { 485 if(shouldUseOuterJoin()) { 486 normalizer.getStatement().getOuterJoinExpressions().addElement(this); 487 normalizer.getStatement().getOuterJoinedMappingCriteria().addElement(mappingExpression); 488 normalizer.getStatement().getOuterJoinedAdditionalJoinCriteria().addElement(additionalExpressionCriteriaMap()); 489 normalizer.getStatement().getDescriptorsForMultitableInheritanceOnly().add(null); 490 return this; 491 } else { 492 if (isUsingOuterJoinForMultitableInheritance()) { 493 normalizer.getStatement().getOuterJoinExpressions().addElement(null); 494 normalizer.getStatement().getOuterJoinedMappingCriteria().addElement(null); 495 normalizer.getStatement().getOuterJoinedAdditionalJoinCriteria().addElement(additionalExpressionCriteriaMap()); 496 normalizer.getStatement().getDescriptorsForMultitableInheritanceOnly().add(getMapping().getReferenceDescriptor()); 497 } 499 } 500 } 501 502 if (foreignKeyJoinPointer != null) { 505 foreignKeyJoinPointer.add(mappingExpression); 510 } else { 511 normalizer.addAdditionalExpression(mappingExpression.and(additionalExpressionCriteria())); 512 } 513 } 514 515 return this; 517 } 518 519 523 public void printSQL(ExpressionSQLPrinter printer) { 524 if (isAttribute()) { 525 printer.printField(getAliasedField()); 526 } 527 528 if ((getMapping() != null) && getMapping().isDirectCollectionMapping()) { 536 DirectCollectionMapping directCollectionMapping = (DirectCollectionMapping)getMapping(); 537 538 TableExpression table = (TableExpression)getTable(directCollectionMapping.getReferenceTable()); 540 DatabaseTable aliasedTable = table.aliasForTable(table.getTable()); 541 DatabaseField aliasedField = (DatabaseField)directCollectionMapping.getDirectField().clone(); 542 aliasedField.setTable(aliasedTable); 543 printer.printField(aliasedField); 544 } 545 } 546 547 551 public void printJava(ExpressionJavaPrinter printer) { 552 getBaseExpression().printJava(printer); 553 if (!shouldUseOuterJoin()) { 554 if (!shouldQueryToManyRelationship()) { 555 printer.printString(".get("); 556 } else { 557 printer.printString(".anyOf("); 558 } 559 } else { 560 if (!shouldQueryToManyRelationship()) { 561 printer.printString(".getAllowingNull("); 562 } else { 563 printer.printString(".anyOfAllowingNone("); 564 } 565 } 566 printer.printString("\"" + getName() + "\")"); 567 } 568 569 574 public Expression rebuildOn(Expression newBase) { 575 Expression newLocalBase = getBaseExpression().rebuildOn(newBase); 576 QueryKeyExpression result = null; 577 578 if (shouldUseOuterJoin) { 580 result = (QueryKeyExpression)newLocalBase.getAllowingNull(getName()); 581 } else { 582 result = (QueryKeyExpression)newLocalBase.get(getName()); 583 } 584 if (shouldQueryToManyRelationship) { 585 result.doQueryToManyRelationship(); 586 } 587 return result; 588 } 589 590 598 public Expression rebuildOn(Expression oldBase, Expression newBase) { 599 if (this == oldBase) { 600 return newBase; 601 } 602 Expression newLocalBase = ((QueryKeyExpression)getBaseExpression()).rebuildOn(oldBase, newBase); 603 QueryKeyExpression result = null; 604 605 if (shouldUseOuterJoin) { 607 result = (QueryKeyExpression)newLocalBase.getAllowingNull(getName()); 608 } else { 609 result = (QueryKeyExpression)newLocalBase.get(getName()); 610 } 611 if (shouldQueryToManyRelationship) { 612 result.doQueryToManyRelationship(); 613 } 614 result.setSelectIfOrderedBy(selectIfOrderedBy()); 615 return result; 616 } 617 618 621 protected void resetCache() { 622 hasMapping = true; 623 mapping = null; 624 hasQueryKey = true; 625 queryKey = null; 626 } 627 628 public boolean shouldQueryToManyRelationship() { 629 return shouldQueryToManyRelationship; 630 } 631 632 639 public Expression twistedForBaseAndContext(Expression newBase, Expression context) { 640 Expression twistedBase = getBaseExpression().twistedForBaseAndContext(newBase, context); 641 QueryKeyExpression result = (QueryKeyExpression)twistedBase.get(getName()); 642 if (shouldUseOuterJoin) { 643 result.doUseOuterJoin(); 644 } 645 if (shouldQueryToManyRelationship) { 646 result.doQueryToManyRelationship(); 647 } 648 return result; 649 650 } 651 652 655 public void validateNode() { 656 if ((getQueryKeyOrNull() == null) && (getMapping() == null)) { 657 throw QueryException.invalidQueryKeyInExpression(getName()); 658 } 659 660 QueryKey queryKey = getQueryKeyOrNull(); 661 DatabaseMapping mapping = getMapping(); 662 663 Object theOneThatsNotNull = null; 664 if (queryKey != null) { 665 theOneThatsNotNull = queryKey; 666 } 667 if (mapping != null) { 668 theOneThatsNotNull = mapping; 669 } 670 671 boolean qkIsToMany = false; 672 if (queryKey != null) { 673 qkIsToMany = queryKey.isManyToManyQueryKey() || queryKey.isOneToManyQueryKey(); 674 } 675 if (mapping != null) { 676 if (shouldUseOuterJoin && (!(mapping.isOneToOneMapping() || mapping.isOneToManyMapping() || mapping.isManyToManyMapping() || mapping.isAggregateCollectionMapping() || mapping.isDirectCollectionMapping()))) { 678 throw QueryException.outerJoinIsOnlyValidForOneToOneMappings(getMapping()); 679 } 680 qkIsToMany = mapping.isCollectionMapping(); 681 } 682 if ((!shouldQueryToManyRelationship()) && qkIsToMany && (!mapping.isNestedTableMapping())) { 683 throw QueryException.invalidUseOfToManyQueryKeyInExpression(theOneThatsNotNull); 684 } 685 if (shouldQueryToManyRelationship() && !qkIsToMany) { 686 throw QueryException.invalidUseOfAnyOfInExpression(theOneThatsNotNull); 687 } 688 } 689 690 695 public Object valueFromObject(Object object, AbstractSession session, AbstractRecord translationRow, InMemoryQueryIndirectionPolicy valueHolderPolicy, boolean isObjectUnregistered) { 696 if ((getBuilder() != getBaseExpression()) && getBaseExpression().isQueryKeyExpression()) { 698 object = getBaseExpression().valueFromObject(object, session, translationRow, valueHolderPolicy, isObjectUnregistered); 699 700 if (object == null) { 703 return null; 704 } 705 706 if (object instanceof Vector) { 709 Vector comparisonVector = new Vector(((Vector)object).size() + 2); 710 for (Enumeration valuesToIterate = (Enumeration)((Vector)object).elements(); 711 valuesToIterate.hasMoreElements();) { 712 Object vectorObject = (Object )valuesToIterate.nextElement(); 713 if (vectorObject == null) { 714 comparisonVector.addElement(vectorObject); 715 } else { 716 Object valueOrValues = valuesFromCollection(vectorObject, session, valueHolderPolicy, isObjectUnregistered); 717 718 if (valueOrValues instanceof Vector) { 720 for (Enumeration nestedValuesToIterate = (Enumeration)((Vector)valueOrValues).elements(); 721 nestedValuesToIterate.hasMoreElements();) { 722 comparisonVector.addElement(nestedValuesToIterate.nextElement()); 723 } 724 } else { 725 comparisonVector.addElement(valueOrValues); 726 } 727 } 728 } 729 return comparisonVector; 730 } 731 } 732 return valuesFromCollection(object, session, valueHolderPolicy, isObjectUnregistered); 733 } 734 735 740 public Object valuesFromCollection(Object object, AbstractSession session, InMemoryQueryIndirectionPolicy valueHolderPolicy, boolean isObjectUnregistered) { 741 boolean readMappingFromQueryKey = false; 744 if (getMapping() == null) { 745 getMappingFromQueryKey(); 746 readMappingFromQueryKey = true; 747 } 748 749 DatabaseMapping mapping = this.mapping; 753 if (mapping.getDescriptor().hasInheritance() && (mapping.getDescriptor().getJavaClass() != object.getClass())) { 754 mapping = session.getDescriptor(object.getClass()).getObjectBuilder().getMappingForAttributeName(getName()); 755 } 756 757 if (mapping.getDescriptor().hasFetchGroupManager()) { 759 FetchGroupManager fetchGroupMgr = mapping.getDescriptor().getFetchGroupManager(); 760 if (fetchGroupMgr.isPartialObject(object) && (!fetchGroupMgr.isAttributeFetched(object, mapping.getAttributeName()))) { 761 throw QueryException.cannotConformUnfetchedAttribute(mapping.getAttributeName()); 763 } 764 } 765 766 if (mapping.isForeignReferenceMapping()) { 767 Object valueFromMapping = mapping.getAttributeValueFromObject(object); 769 if (!((ForeignReferenceMapping)mapping).getIndirectionPolicy().objectIsInstantiated(valueFromMapping)) { 770 if (!valueHolderPolicy.shouldTriggerIndirection()) { 771 throw QueryException.mustInstantiateValueholders(); } 775 776 } 778 Object valueToIterate = mapping.getRealAttributeValueFromObject(object, session); 779 UnitOfWorkImpl uow = isObjectUnregistered ? (UnitOfWorkImpl)session : null; 780 781 if (mapping.isCollectionMapping() && (valueToIterate != null)) { 788 valueToIterate = mapping.getContainerPolicy().vectorFor(valueToIterate, session); 791 792 if (isObjectUnregistered && (uow.getCloneMapping().get(object) == null)) { 796 Vector objectValues = (Vector)valueToIterate; 797 for (int i = 0; i < objectValues.size(); i++) { 798 Object original = objectValues.elementAt(i); 799 Object clone = uow.getIdentityMapAccessorInstance().getIdentityMapManager().getFromIdentityMap(original); 800 if (clone != null) { 801 objectValues.setElementAt(clone, i); 802 } 803 } 804 } 805 806 } else if (isObjectUnregistered && (uow.getCloneMapping().get(object) == null)) { 812 Object clone = uow.getIdentityMapAccessorInstance().getIdentityMapManager().getFromIdentityMap(valueToIterate); 813 if (clone != null) { 814 valueToIterate = clone; 815 } 816 } 817 return valueToIterate; 818 } else if (mapping.isDirectToFieldMapping()) { 819 return ((AbstractDirectMapping)mapping).valueFromObject(object, mapping.getField(), session); 820 } else if (mapping.isAggregateMapping()) { 821 Object aggregateValue = ((AggregateMapping)mapping).getAttributeValueFromObject(object); 822 ; 823 while (readMappingFromQueryKey && mapping.isAggregateObjectMapping() && !((AggregateObjectMapping)mapping).getReferenceClass().equals(queryKey.getDescriptor().getJavaClass())) { 825 mapping = mapping.getReferenceDescriptor().getObjectBuilder().getMappingForField(((DirectQueryKey)queryKey).getField()); 826 aggregateValue = mapping.getRealAttributeValueFromObject(aggregateValue, session); 827 } 828 return aggregateValue; 829 } else { 830 throw QueryException.cannotConformExpression(); 831 } 832 } 833 834 838 public void writeDescriptionOn(BufferedWriter writer) throws IOException { 839 writer.write(getName()); 840 writer.write(tableAliasesDescription()); 841 } 842 843 848 public boolean isNormalizationRequired() { 849 return shouldQueryToManyRelationship() || 850 851 getMapping() == null || 855 856 ((shouldUseOuterJoin() || isUsingOuterJoinForMultitableInheritance()) && !getSession().getPlatform().shouldPrintOuterJoinInWhereClause()) || 861 (shouldUseOuterJoin() && getSession().getPlatform().isInformixOuterJoin()); 862 } 863 } | Popular Tags |