1 23 24 30 31 package com.sun.jdo.spi.persistence.support.sqlstore.model; 32 33 import org.netbeans.modules.dbschema.ColumnElement; 34 import org.netbeans.modules.dbschema.ColumnPairElement; 35 import org.netbeans.modules.dbschema.TableElement; 36 import com.sun.jdo.api.persistence.model.Model; 37 import com.sun.jdo.api.persistence.model.jdo.ConcurrencyGroupElement; 38 import com.sun.jdo.api.persistence.model.jdo.PersistenceClassElement; 39 import com.sun.jdo.api.persistence.model.jdo.PersistenceFieldElement; 40 import com.sun.jdo.api.persistence.model.jdo.RelationshipElement; 41 import com.sun.jdo.api.persistence.model.mapping.MappingClassElement; 42 import com.sun.jdo.api.persistence.model.mapping.MappingFieldElement; 43 import com.sun.jdo.api.persistence.model.mapping.MappingRelationshipElement; 44 import com.sun.jdo.api.persistence.model.mapping.impl.*; 45 import com.sun.jdo.api.persistence.support.*; 46 import com.sun.jdo.spi.persistence.support.sqlstore.*; 47 import com.sun.jdo.spi.persistence.support.sqlstore.sql.RetrieveDescImpl; 48 import com.sun.jdo.spi.persistence.support.sqlstore.sql.UpdateObjectDescImpl; 49 import com.sun.jdo.spi.persistence.support.sqlstore.sql.concurrency.*; 50 import com.sun.jdo.spi.persistence.support.sqlstore.sql.generator.UpdateQueryPlan; 51 import com.sun.jdo.spi.persistence.utility.I18NHelper; 52 import com.sun.jdo.spi.persistence.utility.StringHelper; 53 import com.sun.jdo.spi.persistence.utility.logging.Logger; 54 55 import java.lang.reflect.Field ; 56 import java.util.*; 57 58 61 public class ClassDesc 62 implements com.sun.jdo.spi.persistence.support.sqlstore.PersistenceConfig { 63 64 private ArrayList fetchGroups; 65 66 private int maxHierarchicalGroupID; 67 68 72 private boolean hasLocalNonDFGField; 73 74 75 public ArrayList fields; 76 77 78 public ArrayList hiddenFields; 79 80 81 public ArrayList foreignFields; 82 83 84 private LocalFieldDesc[] versionFields; 85 86 private ArrayList tables; 87 88 private Class pcClass; 89 90 private Class oidClass; 91 92 public int maxFields; 93 94 public int maxVisibleFields; 95 96 public int maxHiddenFields; 97 98 private Concurrency optimisticConcurrency; 99 100 private Concurrency checkDirtyConcurrency; 101 102 private Concurrency databaseConcurrency; 103 104 private Concurrency explicitConcurrency; 105 106 private MappingClassElementImpl mdConfig; 107 108 private ClassLoader classLoader; 109 110 private PersistenceClassElement pcElement; 111 112 private PersistenceFieldElement[] persistentFields; 113 114 private Field keyFields[]; 115 private String keyFieldNames[]; 116 private LocalFieldDesc[] keyFieldDescs; 117 118 119 private static Logger logger = LogHelperSQLStore.getLogger(); 120 121 122 private final Map retrieveDescCache = new HashMap(); 123 124 129 private final Map foreignRetrieveDescCache = new HashMap(); 130 131 132 private RetrieveDesc retrieveDescForVerification; 133 private Object retrieveDescForVerificationSynchObj = new Object (); 134 135 136 private final Map updateQueryPlanCache = new HashMap(); 137 138 139 private UpdateQueryPlan updateQueryPlanForInsert; 140 private Object updateQueryPlanForInsertSynchObj = new Object (); 141 142 143 private UpdateQueryPlan updateQueryPlanForDelete; 144 private Object updateQueryPlanForDeleteSynchObj = new Object (); 145 146 147 private final static ResourceBundle messages = I18NHelper.loadBundle( 148 "com.sun.jdo.spi.persistence.support.sqlstore.Bundle", ClassDesc.class.getClassLoader()); 150 151 public ClassDesc(MappingClassElement mdConfig, Class pcClass) { 152 153 this.mdConfig = (MappingClassElementImpl) mdConfig; 154 pcElement = this.mdConfig.getPersistenceElement(); 155 this.pcClass = pcClass; 156 classLoader = pcClass.getClassLoader(); 157 158 fields = new ArrayList(); 159 foreignFields = new ArrayList(); 160 tables = new ArrayList(); 161 fetchGroups = new ArrayList(); 162 } 163 164 public String toString() { 165 return getName(); 166 } 167 168 174 static ClassDesc newInstance(Class pcClass) { 175 Model model = Model.RUNTIME; 176 String className = pcClass.getName(); 177 ClassLoader classLoader = pcClass.getClassLoader(); 178 ClassDesc rc = null; 179 180 try { 181 MappingClassElement mdConfig = 182 model.getMappingClass(className, classLoader); 183 184 validateModel(model, className, classLoader); 186 187 rc = new ClassDesc(mdConfig, pcClass); 188 189 } catch (JDOException e) { 190 throw e; 191 } catch (IllegalArgumentException e) { 192 throw new JDOFatalUserException(I18NHelper.getMessage(messages, 193 "core.configuration.loadfailed.class", className), e); } catch (Exception e) { 195 throw new JDOFatalInternalException(I18NHelper.getMessage(messages, 196 "core.configuration.loadfailed.class", className), e); } 198 199 return rc; 200 } 201 202 214 static private void validateModel(Model model, 215 String className, 216 ClassLoader classLoader) { 217 Collection c = null; 218 219 if (!(c = model.validate(className, classLoader, null)).isEmpty()) { 220 Iterator iter = c.iterator(); 221 StringBuffer validationMsgs = new StringBuffer (); 222 223 while (iter.hasNext()) { 224 Exception ex = (Exception ) iter.next(); 225 String validationMsg = ex.getLocalizedMessage(); 226 227 logger.fine(I18NHelper.getMessage(messages, 228 "core.configuration.validationproblem", className, validationMsg)); 230 validationMsgs.append(validationMsg).append('\n'); } 232 throw new JDOFatalUserException(I18NHelper.getMessage(messages, 233 "core.configuration.validationfailed", className, validationMsgs.toString())); 235 } 236 } 237 238 public void initialize(ConfigCache cache) { 239 boolean debug = logger.isLoggable(); 240 if (debug) { 241 logger.fine("sqlstore.model.classdesc.persistconfiginit", mdConfig); } 243 244 loadOidClass(); 245 initializeFields(); 246 computeTrackedPrimitiveFields(); 247 248 initializeTables(); 249 initializeJoinTables(); 250 initializeVersionFields(); 251 initializeConcurrency(); 252 253 initializeKeyFields(); 254 initializeFetchGroups(); 255 256 fixupForeignReferences(cache); 257 fixupFieldProperties(); 258 computeTrackedRelationshipFields(); 259 cleanupTrackedFields(); 260 261 if (hiddenFields != null) { 264 maxHiddenFields = hiddenFields.size(); 265 } 266 maxFields = maxVisibleFields + maxHiddenFields; 267 268 if (debug) { 269 logger.fine("sqlstore.model.classdesc.persistconfiginit.exit"); } 271 } 272 273 private void loadOidClass() { 274 275 if (oidClass != null) return; 276 277 String keyClassName = pcElement.getKeyClass(); 278 String suffix = keyClassName.substring(keyClassName.length() - 4); 279 280 if (suffix.compareToIgnoreCase(".oid") == 0) { StringBuffer buf = new StringBuffer (keyClassName); 285 286 buf.setCharAt(buf.length() - 4, '$'); 287 keyClassName = buf.toString(); 288 } 289 290 try { 291 oidClass = Class.forName(keyClassName, true, classLoader); 292 } catch (Throwable e) { 293 throw new JDOFatalInternalException(I18NHelper.getMessage(messages, 294 "core.configuration.cantloadclass", keyClassName)); } 296 297 if (logger.isLoggable()) { 298 logger.fine("sqlstore.model.classdesc.loadedclass", oidClass); } 300 } 301 302 306 private void initializeFields() { 307 ArrayList concurrencyGroups = new ArrayList(); 308 persistentFields = pcElement.getFields(); 309 310 for (int i = 0; i < persistentFields.length; i++) { 311 PersistenceFieldElement pcf = persistentFields[i]; 312 MappingFieldElementImpl mdf = (MappingFieldElementImpl) mdConfig.getField(pcf.getName()); 313 314 if (mdf == null) { 315 throw new JDOFatalUserException(I18NHelper.getMessage(messages, 316 "core.configuration.fieldnotmapped", pcf.getName(), pcElement.getName())); 318 } 319 320 FieldDesc f; 321 322 if (!(mdf instanceof MappingRelationshipElement)) { 323 f = createLocalField(mdf); 324 } else { 325 f = createForeignField((RelationshipElement) pcf, (MappingRelationshipElementImpl) mdf); 326 } 327 328 initializeFetchAndConcurrencyGroup(f, pcf, mdf, concurrencyGroups); 329 330 if (mdf.isReadOnly()) { 331 f.sqlProperties |= FieldDesc.PROP_READ_ONLY; 332 } 333 334 try { 335 f.setupDesc(pcClass, pcf.getName()); 336 } catch (JDOException e) { 337 throw e; 338 } catch (Exception e) { 339 throw new JDOFatalInternalException(I18NHelper.getMessage(messages, 340 "core.configuration.loadfailed.field", pcf.getName(), pcElement.getName()), e); 342 } 343 344 f.absoluteID = pcf.getFieldNumber(); 345 346 addField(f); 347 348 if (logger.isLoggable(Logger.FINEST)) { 349 Object [] items = new Object [] {f.getName(),new Integer (f.absoluteID)}; 350 logger.finest("sqlstore.model.classdesc.fieldinfo", items); } 352 } 353 354 this.maxVisibleFields = fields.size(); 355 } 356 357 362 private LocalFieldDesc createLocalField(MappingFieldElementImpl mdf) { 363 ArrayList columnDesc = mdf.getColumnObjects(); 364 365 if ((columnDesc == null) || (columnDesc.size() == 0)) { 367 throw new JDOFatalUserException(I18NHelper.getMessage(messages, 368 "core.configuration.fieldnotmapped", mdf.getName(), pcElement.getName())); 370 } 371 return new LocalFieldDesc(this, columnDesc); 372 } 373 374 382 private LocalFieldDesc createLocalHiddenField(ColumnElement column) { 383 ArrayList columnDesc = new ArrayList(); 384 columnDesc.add(column); 385 LocalFieldDesc lf = new LocalFieldDesc(this, columnDesc); 386 387 if (hiddenFields == null) { 388 hiddenFields = new ArrayList(); 389 } 390 hiddenFields.add(lf); 391 392 lf.absoluteID = -hiddenFields.size(); 394 395 if (logger.isLoggable(Logger.FINEST)) { 396 Object [] items = new Object [] {pcClass,lf.getName(),column.getName().getFullName()}; 397 logger.finest("sqlstore.model.classdesc.getlocalfielddesc", items); } 399 400 return lf; 401 } 402 403 private FieldDesc createForeignField(RelationshipElement fpcf, 404 MappingRelationshipElementImpl fmdf) { 405 406 ForeignFieldDesc ff = new ForeignFieldDesc(this); 407 408 addForeignField(ff); 409 410 ff.cardinalityLWB = fpcf.getLowerBound(); 411 ff.cardinalityUPB = fpcf.getUpperBound(); 412 ff.deleteAction = fpcf.getDeleteAction(); 413 414 initializeColumnLists(ff, fmdf); 415 416 if (Model.RUNTIME.isCollection(fpcf.getCollectionClass()) && 419 (ff.cardinalityUPB <= 1)) { 420 ff.cardinalityUPB = Integer.MAX_VALUE; 421 } 422 423 if (ff.cardinalityUPB > 1) { 424 try { 425 ff.setComponentType(Class.forName(fpcf.getElementClass(), true, classLoader)); 426 } catch (Throwable e) { 427 logger.log(Logger.WARNING, "sqlstore.exception.log", e); 428 } 429 } 430 431 return ff; 432 } 433 434 private void initializeColumnLists(ForeignFieldDesc ff, MappingRelationshipElementImpl fmdf) { 435 ArrayList assocPairs = fmdf.getAssociatedColumnObjects(); 436 ArrayList pairs = fmdf.getColumnObjects(); 437 ArrayList localColumns = new ArrayList(); 438 ArrayList foreignColumns = new ArrayList(); 439 440 if ((assocPairs == null) || (assocPairs.size() == 0)) { 442 for (int i = 0; i < pairs.size(); i++) { 443 ColumnPairElement fce = (ColumnPairElement) pairs.get(i); 444 localColumns.add(fce.getLocalColumn()); 445 foreignColumns.add(fce.getReferencedColumn()); 446 } 447 448 ff.localColumns = localColumns; 449 ff.foreignColumns = foreignColumns; 450 } else { 451 ArrayList assocLocalColumns = new ArrayList(); 452 ArrayList assocForeignColumns = new ArrayList(); 453 454 for (int i = 0; i < pairs.size(); i++) { 455 ColumnPairElement alc = (ColumnPairElement) pairs.get(i); 456 localColumns.add(alc.getLocalColumn()); 457 assocLocalColumns.add(alc.getReferencedColumn()); 458 } 459 460 for (int i = 0; i < assocPairs.size(); i++) { 461 ColumnPairElement afc = (ColumnPairElement) assocPairs.get(i); 462 assocForeignColumns.add(afc.getLocalColumn()); 463 foreignColumns.add(afc.getReferencedColumn()); 464 } 465 466 ff.localColumns = localColumns; 467 ff.assocLocalColumns = assocLocalColumns; 468 ff.assocForeignColumns = assocForeignColumns; 469 ff.foreignColumns = foreignColumns; 470 } 471 } 472 473 private void initializeFetchAndConcurrencyGroup(FieldDesc f, 474 PersistenceFieldElement pcf, 475 MappingFieldElementImpl mdf, 476 ArrayList concurrencyGroups) { 477 f.fetchGroup = mdf.getFetchGroup(); 478 479 ConcurrencyGroupElement cgroups[] = pcf.getConcurrencyGroups(); 485 487 if ((cgroups == null) || (cgroups.length == 0)) { 488 if (f.fetchGroup == FieldDesc.GROUP_DEFAULT) { 489 f.concurrencyGroup = f.fetchGroup; 490 } 491 } else { 492 ConcurrencyGroupElement cge = cgroups[0]; 493 int index = 0; 494 495 if ((index = concurrencyGroups.indexOf(cge)) == -1) { 496 index = concurrencyGroups.size(); 497 concurrencyGroups.add(cge); 498 } 499 500 f.concurrencyGroup = index; 501 } 502 } 503 504 private void createSecondaryTableKey(TableDesc table, MappingReferenceKeyElementImpl mappingSecondaryKey) { 505 506 ColumnPairElement pairs[] = mappingSecondaryKey.getColumnPairs(); 507 KeyDesc referencingKey = new KeyDesc(); 508 KeyDesc referencedKey = new KeyDesc(); 509 TableDesc secondaryTable = findTableDesc(((MappingTableElementImpl) mappingSecondaryKey.getTable()).getTableObject()); 510 511 for (int i = 0; i < pairs.length; i++) { 512 ColumnPairElement pair = pairs[i]; 513 514 ColumnElement lc = pair.getLocalColumn(); 515 ColumnElement fc = pair.getReferencedColumn(); 516 517 referencingKey.addColumn(lc); 518 519 FieldDesc lf = getLocalFieldDesc(lc); 520 referencingKey.addField(lf); 521 522 lf.fetchGroup = FieldDesc.GROUP_DEFAULT; 527 528 referencedKey.addColumn(fc); 529 referencedKey.addField(getLocalFieldDesc(fc)); 530 } 531 532 table.addSecondaryTableKey(new ReferenceKeyDesc(secondaryTable, referencingKey, referencedKey)); 533 secondaryTable.setPrimaryTableKey(new ReferenceKeyDesc(table, referencedKey, referencingKey)); 534 } 535 536 539 private void initializeTables() { 540 ArrayList mdTables = mdConfig.getTables(); 541 542 createTables(mdTables); 543 processSecondaryTables(mdTables); 544 } 545 546 private void createTables(ArrayList mdTables) { 547 for (int i = 0; i < mdTables.size(); i++) { 548 MappingTableElementImpl mdt = (MappingTableElementImpl) mdTables.get(i); 549 TableDesc t = new TableDesc(mdt.getTableObject()); 550 551 ArrayList keys = mdt.getKeyObjects(); 552 KeyDesc key = new KeyDesc(); 553 t.setKey(key); 554 key.addColumns(keys); 555 556 for (int j = 0; j < keys.size(); j++) { 557 ColumnElement c = (ColumnElement) keys.get(j); 558 559 if (c != null) { 560 key.addField(getLocalFieldDesc(c)); 561 } 562 } 563 564 addTableDesc(t); 565 } 566 } 567 568 576 private void processSecondaryTables(ArrayList mdTables) { 577 578 for (int i = 0; i < tables.size(); i++) { 579 MappingTableElementImpl mdt = (MappingTableElementImpl) mdTables.get(i); 580 TableDesc t = (TableDesc) tables.get(i); 581 ArrayList secondaryKeys = mdt.getReferencingKeys(); 582 583 for (int j = 0; j < secondaryKeys.size(); j++) { 584 MappingReferenceKeyElementImpl mappingSecondaryKey = (MappingReferenceKeyElementImpl) secondaryKeys.get(j); 585 createSecondaryTableKey(t, mappingSecondaryKey); 586 } 587 } 588 } 589 590 private void initializeJoinTables() { 591 Iterator iter = foreignFields.iterator(); 592 593 while (iter.hasNext()) { 594 ForeignFieldDesc ff = (ForeignFieldDesc) iter.next(); 595 596 if (ff.useJoinTable()) { 597 TableElement joinTable = ((ColumnElement) ff.assocLocalColumns.get(0)).getDeclaringTable(); 598 TableDesc joinTableDesc = findTableDesc(joinTable); 599 600 if (joinTableDesc == null) { 601 joinTableDesc = new TableDesc(joinTable); 602 603 joinTableDesc.setJoinTable(true); 605 addTableDesc(joinTableDesc); 606 } 607 } 608 } 609 } 610 611 619 public ArrayList getFetchGroup(int groupID) { 620 int index = 0; 621 622 if (groupID >= FieldDesc.GROUP_NONE) { 623 index = groupID; 624 } else if (groupID < FieldDesc.GROUP_NONE) { 625 index = -groupID + maxHierarchicalGroupID; 626 } 627 628 for (int i = fetchGroups.size(); i <= index; i++) { 629 fetchGroups.add(null); 630 } 631 632 ArrayList group = (ArrayList) fetchGroups.get(index); 633 634 if (group == null) { 635 group = new ArrayList(); 636 fetchGroups.set(index, group); 637 } 638 639 return group; 640 } 641 642 private void addField(FieldDesc f) { 643 fields.add(f); 644 } 645 646 private void addForeignField(ForeignFieldDesc f) { 647 foreignFields.add(f); 648 } 649 650 659 private void initializeFetchGroups() { 660 661 for (int i = 0; i < 2; i++) { 662 ArrayList theFields = null; 663 664 if (i == 0) { 665 theFields = fields; 666 } else { 667 if ((theFields = hiddenFields) == null) 669 continue; 670 } 671 672 for (int j = 0; j < theFields.size(); j++) { 673 FieldDesc f = (FieldDesc) theFields.get(j); 674 675 if (f.fetchGroup > FieldDesc.GROUP_NONE) { 677 getFetchGroup(f.fetchGroup).add(f); 678 } 679 680 if (i == 0 && !f.isRelationshipField() 682 && f.fetchGroup != FieldDesc.GROUP_DEFAULT) { 683 hasLocalNonDFGField = true; 684 } 685 } 686 } 687 688 this.maxHierarchicalGroupID = fetchGroups.size() - 1; 689 690 for (int i = 0; i < fields.size(); i++) { 691 FieldDesc f = (FieldDesc) fields.get(i); 692 693 if (f.fetchGroup < FieldDesc.GROUP_NONE) { 695 getFetchGroup(f.fetchGroup).add(f); 696 } 697 } 698 } 699 700 private void initializeConcurrency() { 701 optimisticConcurrency = new ConcurrencyOptVerify(); 702 optimisticConcurrency.configPersistence(this); 703 checkDirtyConcurrency = new ConcurrencyCheckDirty(); 704 checkDirtyConcurrency.configPersistence(this); 705 databaseConcurrency = new ConcurrencyDBNative(); 706 databaseConcurrency.configPersistence(this); 707 explicitConcurrency = new ConcurrencyDBExplicit(); 708 explicitConcurrency.configPersistence(this); 709 } 710 711 private void initializeKeyFields() { 712 boolean debug = logger.isLoggable(Logger.FINEST); 713 if (oidClass == null) 714 return; 715 716 keyFields = oidClass.getFields(); 717 keyFieldNames = new String [keyFields.length]; 718 keyFieldDescs = new LocalFieldDesc[keyFields.length]; 719 720 if (debug) { 721 logger.finest("sqlstore.model.classdesc.createsqldesc", oidClass); } 723 724 for (int i = 0; i < keyFields.length; i++) { 725 Field kf = keyFields[i]; 726 String name = kf.getName(); 727 keyFieldNames[i] = name; 728 729 if (name.equals("serialVersionUID")) { continue; 731 } 732 733 LocalFieldDesc f = getLocalFieldDesc(name); 734 735 if (f != null) { 736 if (debug) { 737 logger.finest("sqlstore.model.classdesc.pkfield", f.getName()); } 739 740 f.fetchGroup = FieldDesc.GROUP_DEFAULT; 742 f.sqlProperties &= ~(FieldDesc.PROP_REF_INTEGRITY_UPDATES); 743 f.sqlProperties &= ~(FieldDesc.PROP_IN_CONCURRENCY_CHECK); 744 f.sqlProperties |= FieldDesc.PROP_PRIMARY_KEY_FIELD; 745 746 keyFieldDescs[i] = f; 747 } else { 748 throw new JDOFatalUserException(I18NHelper.getMessage(messages, 749 "core.configuration.noneexistentpkfield", name, oidClass.getName(), pcClass.getName())); 751 } 752 } 753 } 754 755 760 private void initializeVersionFields() { 761 int size = mdConfig.getVersionFields().size(); 762 Iterator versionFieldIterator = mdConfig.getVersionFields().iterator(); 763 versionFields = new LocalFieldDesc[size]; 764 765 for (int i = 0; i < size; i++) { 766 MappingFieldElement mdField = (MappingFieldElement) versionFieldIterator.next(); 767 LocalFieldDesc f = (LocalFieldDesc) getField(mdField.getName()); 768 769 if (f != null) { 770 if (logger.isLoggable()) { 771 logger.finest("sqlstore.model.classdesc.vcfield", f.getName()); } 773 774 versionFields[i] = f; 775 registerVersionFieldWithTable(f); 776 777 f.fetchGroup = FieldDesc.GROUP_DEFAULT; 779 f.sqlProperties &= ~(FieldDesc.PROP_REF_INTEGRITY_UPDATES); 780 f.sqlProperties |= FieldDesc.PROP_VERSION_FIELD; 781 } else { 782 throw new JDOFatalUserException(I18NHelper.getMessage(messages, 783 "core.configuration.noneexistentvcfield", mdField.getName(), pcClass.getName())); 785 } 786 } 787 } 788 789 795 private void registerVersionFieldWithTable(LocalFieldDesc versionField) { 796 ColumnElement ce = (ColumnElement) versionField.getColumnElements().next(); 798 Iterator iter = tables.iterator(); 799 800 while (iter.hasNext()) { 801 TableDesc table = (TableDesc) iter.next(); 802 803 if (!table.isJoinTable()) { 804 if (ce.getDeclaringTable() == table.getTableElement()) { 805 table.setVersionField(versionField); 806 break; 807 } 808 } 809 } 810 } 811 812 819 private void computeTrackedPrimitiveFields() { 820 for (int i = 0; i < fields.size(); i++) { 822 FieldDesc f = (FieldDesc) fields.get(i); 823 824 if (!f.isRelationshipField()) { 825 LocalFieldDesc lf = (LocalFieldDesc) f; 826 827 lf.computeTrackedPrimitiveFields(); 828 lf.computePrimaryTrackedPrimitiveField(); 829 } 830 } 831 } 832 833 852 private void computeTrackedRelationshipFields() { 853 for (int i = 0; i < 2; i++) { 855 ArrayList theFields = null; 856 857 if (i == 0) { 859 theFields = this.fields; 860 } else { 861 if ((theFields = this.hiddenFields) == null) { 862 continue; 863 } 864 } 865 866 for (int j = 0; j < theFields.size(); j++) { 867 FieldDesc f = (FieldDesc) theFields.get(j); 868 869 f.computeTrackedRelationshipFields(); 870 } 871 } 872 } 873 874 877 private void cleanupTrackedFields() { 878 879 for (int i = 0; i < fields.size(); i++) { 880 FieldDesc f = (FieldDesc) fields.get(i); 881 882 if (f instanceof LocalFieldDesc) { 883 ((LocalFieldDesc) f).cleanupTrackedFields(); 884 } 885 } 886 } 887 888 894 private void fixupForeignReferences(ConfigCache cache) { 895 896 for (int i = 0; i < foreignFields.size(); i++) { 897 ForeignFieldDesc ff = (ForeignFieldDesc) foreignFields.get(i); 898 Class classType = null; 899 900 if ((classType = ff.getComponentType()) == null) { 901 classType = ff.getType(); 902 } 903 904 ClassDesc foreignConfig = (ClassDesc) cache.getPersistenceConfig(classType); 905 906 if (foreignConfig == null) continue; 907 908 String irName = pcElement.getRelationship(ff.getName()).getInverseRelationshipName(); 910 ForeignFieldDesc inverseField = null; 911 912 if (irName != null) { 913 inverseField = (ForeignFieldDesc) foreignConfig.getField(irName); 914 } 915 916 ff.fixupForeignReference(foreignConfig, inverseField); 917 } 918 } 919 920 private void fixupFieldProperties() { 921 922 for (int i = 0; i < foreignFields.size(); i++) { 923 ForeignFieldDesc ff = (ForeignFieldDesc) foreignFields.get(i); 924 ff.fixupFieldProperties(); 925 } 926 } 927 928 LocalFieldDesc getLocalFieldDesc(ColumnElement column) { 929 LocalFieldDesc result; 930 931 for (int i = 0; i < 2; i++) { 932 ArrayList theFields = null; 933 934 if (i == 0) { 935 theFields = fields; 936 } else { 937 theFields = hiddenFields; 938 } 939 940 if (theFields != null) { 941 for (int j = 0; j < theFields.size(); j++) { 942 FieldDesc f = (FieldDesc) theFields.get(j); 943 944 if (f instanceof LocalFieldDesc) { 945 result = (LocalFieldDesc) f; 946 947 for (int k = 0; k < result.columnDescs.size(); k++) { 948 ColumnElement c = (ColumnElement) result.columnDescs.get(k); 949 950 if (c.getName().getFullName().compareTo(column.getName().getFullName()) == 0) { 952 if ((f.getTrackedFields() != null) && 955 ((f.sqlProperties & FieldDesc.PROP_PRIMARY_TRACKED_FIELD) == 0)) { 956 continue; 957 } 958 959 return result; 960 } 961 } 962 } 963 } 964 } 965 } 966 967 result = createLocalHiddenField(column); 970 971 return result; 972 } 973 974 981 public LocalFieldDesc getLocalFieldDesc(String name) { 982 FieldDesc desc = getField(name); 983 984 if (desc == null) { 985 throw new JDOFatalInternalException(I18NHelper.getMessage(messages, 986 "core.generic.unknownfield", name, getName())); 988 } 989 990 if (!(desc instanceof LocalFieldDesc)) { 991 throw new JDOFatalInternalException(I18NHelper.getMessage(messages, 992 "core.generic.notinstanceof", desc.getClass().getName(), "LocalFieldDesc")); } 995 996 return ((LocalFieldDesc) desc); 997 } 998 999 public TableDesc findTableDesc(TableElement mdTable) { 1000 for (int i = 0; i < tables.size(); i++) { 1001 TableDesc t = (TableDesc) tables.get(i); 1002 1003 if (t.getTableElement().equals(mdTable)) { 1004 return t; 1005 } 1006 } 1007 1008 return null; 1009 } 1010 1011 private void addTableDesc(TableDesc t) { 1012 if (!t.isJoinTable()) { 1014 t.setConsistencyLevel(mdConfig.getConsistencyLevel()); 1017 } 1018 tables.add(t); 1019 } 1020 1021 public int getTableIndex(TableDesc tableDesc) { 1022 return tables.indexOf(tableDesc); 1023 } 1024 1025 public FieldDesc getField(String name) { 1026 for (int i = 0; i < fields.size(); i++) { 1027 FieldDesc f = (FieldDesc) fields.get(i); 1028 1029 if ((f != null) && (f.getName().compareTo(name) == 0)) { 1030 return f; 1031 } 1032 } 1033 1034 if (hiddenFields != null) { 1035 for (int i = 0; i < hiddenFields.size(); i++) { 1036 FieldDesc f = (FieldDesc) hiddenFields.get(i); 1037 1038 if (f.getName().compareTo(name) == 0) { 1039 return f; 1040 } 1041 } 1042 } 1043 1044 return null; 1045 } 1046 1047 public FieldDesc getField(int index) { 1048 if (index >= 0) { 1049 return (FieldDesc) fields.get(index); 1050 } else { 1051 return (FieldDesc) hiddenFields.get(-(index + 1)); 1052 } 1053 } 1054 1055 public Class getPersistenceCapableClass() { 1056 return pcClass; 1057 } 1058 1059 public Class getOidClass() { 1060 return oidClass; 1061 } 1062 1063 public String getName() { 1064 return pcClass.getName(); 1065 } 1066 1067 public Iterator getTables() { 1068 return tables.iterator(); 1069 } 1070 1071 public TableDesc getPrimaryTable() { 1072 return (TableDesc) tables.get(0); 1073 } 1074 1075 public boolean isNavigable() { 1076 return mdConfig.isNavigable(); 1077 } 1078 1079 public boolean hasVersionConsistency() { 1080 return mdConfig.getConsistencyLevel() == MappingClassElement.VERSION_CONSISTENCY; 1081 } 1082 1083 public LocalFieldDesc[] getVersionFields() { 1084 return versionFields; 1085 } 1086 1087 public Concurrency getConcurrency(boolean optimistic) { 1088 1093 Concurrency concurrency = null; 1094 int consistencyLevel = mdConfig.getConsistencyLevel(); 1095 1096 if (consistencyLevel == MappingClassElement.NONE_CONSISTENCY) { 1097 if (optimistic) { 1099 concurrency = (Concurrency) optimisticConcurrency.clone(); 1100 } else { 1101 concurrency = (Concurrency) databaseConcurrency.clone(); 1102 } 1103 1104 } else { 1105 switch(consistencyLevel) { 1110 1111 1116 case MappingClassElement.CHECK_MODIFIED_AT_COMMIT_CONSISTENCY : 1117 concurrency = (Concurrency) checkDirtyConcurrency.clone(); 1118 break; 1119 1120 case MappingClassElement.LOCK_WHEN_LOADED_CONSISTENCY : 1121 concurrency = (Concurrency) explicitConcurrency.clone(); 1124 break; 1125 1126 case MappingClassElement.VERSION_CONSISTENCY : 1127 concurrency = (Concurrency) databaseConcurrency.clone(); 1132 break; 1133 1134 default : 1139 throw new JDOUnsupportedOptionException(I18NHelper.getMessage(messages, 1140 "core.configuration.unsupportedconsistencylevel", pcClass)); } 1142 } 1143 1144 return concurrency; 1145 } 1146 1147 1154 public boolean hasModifiedCheckAtCommitConsistency() { 1155 return(mdConfig.getConsistencyLevel() == 1156 MappingClassElement.CHECK_MODIFIED_AT_COMMIT_CONSISTENCY); 1157 } 1158 1159 public boolean isPKField(int index) { 1160 return persistentFields[index].isKey(); 1161 } 1162 1163 1167 public Field [] getKeyFields() { 1168 return keyFields; 1169 } 1170 1171 1175 public String [] getKeyFieldNames() { 1176 return keyFieldNames; 1177 } 1178 1179 1183 public LocalFieldDesc[] getKeyFieldDescs() { 1184 return keyFieldDescs; 1185 } 1186 1187 1195 public SQLStateManager newStateManagerInstance(PersistenceStore store) { 1196 return new SQLStateManager(store, this); 1197 } 1198 1199 1218 public RetrieveDesc getRetrieveDescForPKQuery(FieldDesc additionalField, PersistenceStore store) { 1219 RetrieveDescImpl rd = null; 1220 String cacheKey = generateRDCacheKey(additionalField); 1221 1222 synchronized (retrieveDescCache) { 1223 rd = (RetrieveDescImpl) retrieveDescCache.get(cacheKey); 1225 if (rd == null) { 1227 rd = (RetrieveDescImpl) store.getRetrieveDesc(pcClass); 1228 if (additionalField != null) { 1229 RetrieveDesc frd = null; 1230 String name = additionalField.getName(); 1231 if (additionalField instanceof ForeignFieldDesc) { 1234 Class additionalClass = ((ForeignFieldDesc) additionalField). 1235 foreignConfig.getPersistenceCapableClass(); 1236 1237 frd = store.getRetrieveDesc(additionalClass); 1238 } 1239 1240 rd.addPrefetchedField(name, frd); 1241 } 1242 1243 addPKConstraints(rd); 1244 retrieveDescCache.put(cacheKey, rd); 1246 } 1247 } 1248 1249 return rd; 1250 } 1251 1252 1279 public RetrieveDesc getRetrieveDescForFKQuery(ForeignFieldDesc foreignField, PersistenceStore store) { 1280 RetrieveDescImpl rd = null; 1281 String cacheKey = generateRDCacheKey(foreignField); 1282 1283 synchronized (foreignRetrieveDescCache) { 1284 rd = (RetrieveDescImpl) foreignRetrieveDescCache.get(cacheKey); 1286 if (rd == null) { 1288 rd = (RetrieveDescImpl) store.getRetrieveDesc(foreignField.foreignConfig.getPersistenceCapableClass()); 1289 1290 addFKConstraints(rd, foreignField); 1291 foreignRetrieveDescCache.put(cacheKey, rd); 1293 } 1294 } 1295 1296 return rd; 1297 } 1298 1299 1306 public RetrieveDesc getRetrieveDescForVerificationQuery(PersistenceStore store) { 1307 1308 assert hasVersionConsistency(); 1309 1310 synchronized(retrieveDescForVerificationSynchObj) { 1311 if (retrieveDescForVerification == null) { 1312 RetrieveDescImpl rd = (RetrieveDescImpl) store.getRetrieveDesc(pcClass); 1313 1314 int index = addPKConstraints(rd); 1315 rd.addParameterConstraints(versionFields, index); 1316 rd.setOption(RetrieveDescImpl.OPT_VERIFY); 1317 1318 retrieveDescForVerification = rd; 1319 } 1320 } 1321 return retrieveDescForVerification; 1322 } 1323 1324 1328 private int addPKConstraints(RetrieveDescImpl rd) { 1329 rd.addParameterConstraints(keyFieldDescs, 0); 1331 1332 return keyFieldDescs.length; 1333 } 1334 1335 1339 private void addFKConstraints(RetrieveDescImpl rd, ForeignFieldDesc foreignField) { 1340 for (int i = 0; i < foreignField.foreignFields.size(); i++) { 1341 LocalFieldDesc fff = (LocalFieldDesc) foreignField.foreignFields.get(i); 1342 rd.addParameterConstraint(fff, i); 1343 } 1344 } 1345 1346 1360 private String generateRDCacheKey(FieldDesc additionalField) 1361 { 1362 StringBuffer key = new StringBuffer (); 1363 1364 key.append(pcClass.getName()); 1365 1366 if (additionalField != null) { 1367 key.append('/'); 1369 key.append(additionalField.getName()); 1370 key.append('/'); 1371 key.append(additionalField.absoluteID); 1372 } 1373 1374 return key.toString(); 1375 } 1376 1377 1388 public boolean hasLocalNonDFGFields() { 1389 return hasLocalNonDFGField; 1394 } 1395 1396 1402 public UpdateQueryPlan getUpdateQueryPlan( 1403 UpdateObjectDescImpl desc, SQLStoreManager store) 1404 { 1405 switch (desc.getUpdateAction()) { 1406 case ActionDesc.LOG_CREATE: 1407 return getUpdateQueryPlanForInsert(desc, store); 1408 case ActionDesc.LOG_DESTROY: 1409 return getUpdateQueryPlanForDelete(desc, store); 1410 case ActionDesc.LOG_UPDATE: 1411 return getUpdateQueryPlanForUpdate(desc, store); 1412 default: 1413 return null; 1416 } 1417 } 1418 1419 1420 private UpdateQueryPlan getUpdateQueryPlanForInsert( 1421 UpdateObjectDescImpl desc, SQLStoreManager store) 1422 { 1423 synchronized(updateQueryPlanForInsertSynchObj) { 1424 if (updateQueryPlanForInsert == null) { 1425 updateQueryPlanForInsert = buildQueryPlan(store, desc); 1426 } 1427 } 1428 return updateQueryPlanForInsert; 1429 } 1430 1431 1432 private UpdateQueryPlan getUpdateQueryPlanForDelete( 1433 UpdateObjectDescImpl desc, SQLStoreManager store) 1434 { 1435 synchronized(updateQueryPlanForDeleteSynchObj) { 1436 if (updateQueryPlanForDelete == null) { 1437 updateQueryPlanForDelete = buildQueryPlan(store, desc); 1438 } 1439 } 1440 return updateQueryPlanForDelete; 1441 } 1442 1443 1444 private UpdateQueryPlan getUpdateQueryPlanForUpdate( 1445 UpdateObjectDescImpl desc, SQLStoreManager store) 1446 { 1447 String key = getSortedFieldNumbers(desc.getUpdatedFields()); 1448 UpdateQueryPlan plan; 1449 synchronized(updateQueryPlanCache) { 1450 plan = (UpdateQueryPlan)updateQueryPlanCache.get(key); 1451 if (plan == null) { 1452 plan = buildQueryPlan(store, desc); 1453 updateQueryPlanCache.put(key, plan); 1454 } 1455 } 1456 return plan; 1457 } 1458 1459 1470 private UpdateQueryPlan buildQueryPlan(SQLStoreManager store, 1471 UpdateObjectDescImpl desc) { 1472 UpdateQueryPlan plan; 1473 1474 plan = new UpdateQueryPlan(desc, store); 1475 plan.build(true); 1476 1477 plan.getStatements(); 1480 1481 return plan; 1482 } 1483 1484 1492 private String getSortedFieldNumbers(List fields) 1493 { 1494 int size = fields.size(); 1496 int [] fieldNos = new int[size]; 1497 for (int i = 0; i < size; i++) { 1498 FieldDesc f = (FieldDesc)fields.get(i); 1499 fieldNos[i] = f.absoluteID; 1500 } 1501 Arrays.sort(fieldNos); 1502 return StringHelper.intArrayToSeparatedList(fieldNos, ","); } 1504 1505} 1506 | Popular Tags |