1/*- 2 * See the file LICENSE for redistribution information. 3 * 4 * Copyright (c) 2002-2009 Oracle. All rights reserved. 5 * 6 * $Id$ 7 */ 8 9package com.sleepycat.persist.impl; 10 11import java.io.Serializable; 12import java.util.HashSet; 13import java.util.IdentityHashMap; 14import java.util.List; 15import java.util.Map; 16import java.util.Set; 17 18import com.sleepycat.persist.evolve.Converter; 19import com.sleepycat.persist.model.ClassMetadata; 20import com.sleepycat.persist.model.EntityMetadata; 21import com.sleepycat.persist.model.EntityModel; 22import com.sleepycat.persist.model.FieldMetadata; 23import com.sleepycat.persist.model.PrimaryKeyMetadata; 24import com.sleepycat.persist.model.SecondaryKeyMetadata; 25import com.sleepycat.persist.raw.RawField; 26import com.sleepycat.persist.raw.RawObject; 27import com.sleepycat.persist.raw.RawType; 28 29/** 30 * The base class for all object formats. Formats are used to define the 31 * stored layout for all persistent classes, including simple types. 32 * 33 * The design documentation below describes the storage format for entities and 34 * its relationship to information stored per format in the catalog. 35 * 36 * Requirements 37 * ------------ 38 * + Provides EntityBinding for objects and EntryBinding for keys. 39 * + Provides SecondaryKeyCreator, SecondaryMultiKeyCreator and 40 * SecondaryMultiKeyNullifier (SecondaryKeyNullifier is redundant). 41 * + Works with reflection and bytecode enhancement. 42 * + For reflection only, works with any entity model not just annotations. 43 * + Bindings are usable independently of the persist API. 44 * + Performance is almost equivalent to hand coded tuple bindings. 45 * + Small performance penalty for compatible class changes (new fields, 46 * widening). 47 * + Secondary key create/nullify do not have to deserialize the entire record; 48 * in other words, store secondary keys at the start of the data. 49 * 50 * Class Format 51 * ------------ 52 * Every distinct class format is given a unique format ID. Class IDs are not 53 * equivalent to class version numbers (as in the version property of @Entity 54 * and @Persistent) because the format can change when the version number does 55 * not. Changes that cause a unique format ID to be assigned are: 56 * 57 * + Add field. 58 * + Widen field type. 59 * + Change primitive type to primitive wrapper class. 60 * + Add or drop secondary key. 61 * + Any incompatible class change. 62 * 63 * The last item, incompatible class changes, also correspond to a class 64 * version change. 65 * 66 * For each distinct class format the following information is conceptually 67 * stored in the catalog, keyed by format ID. 68 * 69 * - Class name 70 * - Class version number 71 * - Superclass format 72 * - Kind: simple, enum, complex, array 73 * - For kind == simple: 74 * - Primitive class 75 * - For kind == enum: 76 * - Array of constant names, sorted by name. 77 * - For kind == complex: 78 * - Primary key fieldInfo, or null if no primary key is declared 79 * - Array of secondary key fieldInfo, sorted by field name 80 * - Array of other fieldInfo, sorted by field name 81 * - For kind == array: 82 * - Component class format 83 * - Number of array dimensions 84 * - Other metadata for RawType 85 * 86 * Where fieldInfo is: 87 * - Field name 88 * - Field class 89 * - Other metadata for RawField 90 * 91 * Data Layout 92 * ----------- 93 * For each entity instance the data layout is as follows: 94 * 95 * instanceData: formatId keyFields... nonKeyFields... 96 * keyFields: fieldValue... 97 * nonKeyFields: fieldValue... 98 * 99 * The formatId is the (positive non-zero) ID of a class format, defined above. 100 * This is ID of the most derived class of the instance. It is stored as a 101 * packed integer. 102 * 103 * Following the format ID, zero or more sets of secondary key field values 104 * appear, followed by zero or more sets of other class field values. 105 * 106 * The keyFields are the sets of secondary key fields for each class in order 107 * of the highest superclass first. Within a class, fields are ordered by 108 * field name. 109 * 110 * The nonKeyFields are the sets of other non-key fields for each class in 111 * order of the highest superclass first. Within a class, fields are ordered 112 * by field name. 113 * 114 * A field value is: 115 * 116 * fieldValue: primitiveValue 117 * | nullId 118 * | instanceRef 119 * | instanceData 120 * | simpleValue 121 * | enumValue 122 * | arrayValue 123 * 124 * For a primitive type, a primitive value is used as defined for tuple 125 * bindings. For float and double, sorted float and sorted double tuple values 126 * are used. 127 * 128 * For a non-primitive type with a null value, a nullId is used that has a zero 129 * (illegal formatId) value. This includes String and other simple reference 130 * types. The formatId is stored as a packed integer, meaning that it is 131 * stored as a single zero byte. 132 * 133 * For a non-primitive type, an instanceRef is used for a non-null instance 134 * that appears earlier in the data byte array. An instanceRef is the negation 135 * of the byte offset of the instanceData that appears earlier. It is stored 136 * as a packed integer. 137 * 138 * The remaining rules apply only to reference types with non-null values that 139 * do not appear earlier in the data array. 140 * 141 * For an array type, an array formatId is used that identifies the component 142 * type and the number of array dimensions. This is followed by an array 143 * length (stored as a packed integer) and zero or more fieldValue elements. 144 * For an array with N+1 dimensions where N is greater than zero, the leftmost 145 * dimension is enumerated such that each fieldValue element is itself an array 146 * of N dimensions or null. 147 * 148 * arrayValue: formatId length fieldValue... 149 * 150 * For an enum type, an enumValue is used, consisting of a formatId that 151 * identifies the enum class and an enumIndex (stored as a packed integer) that 152 * identifies the constant name in the enum constant array of the enum class 153 * format: 154 * 155 * enumValue: formatId enumIndex 156 * 157 * For a simple type, a simpleValue is used. This consists of the formatId 158 * that identifies the class followed by the simple type value. For a 159 * primitive wrapper type the simple type value is the corresponding primitive, 160 * for a Date it is the milliseconds as a long primitive, and for BigInteger or 161 * BigDecimal it is a byte array as defined for tuple bindings of these types. 162 * 163 * simpleValue: formatId value 164 * 165 * For all other complex types, an instanceData is used, which is defined 166 * above. 167 * 168 * Secondary Keys 169 * -------------- 170 * For secondary key support we must account for writing and nullifying 171 * specific keys. Rather than instantiating the entity and then performing 172 * the secondary key operation, we strive to perform the secondary key 173 * operation directly on the byte format. 174 * 175 * To create a secondary key we skip over other fields and then copy the bytes 176 * of the embedded key. This approach is very efficient because a) the entity 177 * is not instantiated, and b) the secondary keys are stored at the beginning 178 * of the byte format and can be quickly read. 179 * 180 * To nullify we currently instantiate the raw entity, set the key field to null 181 * (or remove it from the array/collection), and convert the raw entity back to 182 * bytes. Although the performance of this approach is not ideal because it 183 * requires serialization, it avoids the complexity of modifying the packed 184 * serialized format directly, adjusting references to key objects, etc. Plus, 185 * when we nullify a key we are going to write the record, so the serialization 186 * overhead may not be significant. For the record, I tried implementing 187 * nullification of the bytes directly and found it was much too complex. 188 * 189 * Lifecycle 190 * --------- 191 * Format are managed by a Catalog class. Simple formats are managed by 192 * SimpleCatalog, and are copied from the SimpleCatalog by PersistCatalog. 193 * Other formats are managed by PersistCatalog. The lifecycle of a format 194 * instance is: 195 * 196 * - Constructed by the catalog when a format is requested for a Class 197 * that currently has no associated format. 198 * 199 * - The catalog calls setId() and adds the format to its format list 200 * (indexed by format id) and map (keyed by class name). 201 * 202 * - The catalog calls collectRelatedFormats(), where a format can create 203 * additional formats that it needs, or that should also be persistent. 204 * 205 * - The catalog calls initializeIfNeeded(), which calls the initialize() 206 * method of the format class. 207 * 208 * - initialize() should initialize any transient fields in the format. 209 * initialize() can assume that all related formats are available in the 210 * catalog. It may call initializeIfNeeded() for those related formats, if 211 * it needs to interact with an initialized related format; this does not 212 * cause a cycle, because initializeIfNeeded() does nothing for an already 213 * initialized format. 214 * 215 * - The catalog creates a group of related formats at one time, and then 216 * writes its entire list of formats to the catalog DB as a single record. 217 * This grouping reduces the number of writes. 218 * 219 * - When a catalog is opened and the list of existing formats is read. After 220 * a format is deserialized, its initializeIfNeeded() method is called. 221 * setId() and collectRelatedFormats() are not called, since the ID and 222 * related formats are stored in serialized fields. 223 * 224 * - There are two modes for opening an existing catalog: raw mode and normal 225 * mode. In raw mode, the old format is used regardless of whether it 226 * matches the current class definition; in fact the class is not accessed 227 * and does not need to be present. 228 * 229 * - In normal mode, for each existing format that is initialized, a new format 230 * is also created based on the current class and metadata definition. If 231 * the two formats are equal, the new format is discarded. If they are 232 * unequal, the new format becomes the current format and the old format's 233 * evolve() method is called. evolve() is responsible for adjusting the 234 * old format for class evolution. Any number of non-current formats may 235 * exist for a given class, and are setup to evolve the single current format 236 * for the class. 237 * 238 * @author Mark Hayes 239 */ 240public abstract class Format implements Reader, RawType, Serializable { 241 242 private static final long serialVersionUID = 545633644568489850L; 243 244 /** Null reference. */ 245 static final int ID_NULL = 0; 246 /** Object */ 247 static final int ID_OBJECT = 1; 248 /** Boolean */ 249 static final int ID_BOOL = 2; 250 static final int ID_BOOL_W = 3; 251 /** Byte */ 252 static final int ID_BYTE = 4; 253 static final int ID_BYTE_W = 5; 254 /** Short */ 255 static final int ID_SHORT = 6; 256 static final int ID_SHORT_W = 7; 257 /** Integer */ 258 static final int ID_INT = 8; 259 static final int ID_INT_W = 9; 260 /** Long */ 261 static final int ID_LONG = 10; 262 static final int ID_LONG_W = 11; 263 /** Float */ 264 static final int ID_FLOAT = 12; 265 static final int ID_FLOAT_W = 13; 266 /** Double */ 267 static final int ID_DOUBLE = 14; 268 static final int ID_DOUBLE_W = 15; 269 /** Character */ 270 static final int ID_CHAR = 16; 271 static final int ID_CHAR_W = 17; 272 /** String */ 273 static final int ID_STRING = 18; 274 /** BigInteger */ 275 static final int ID_BIGINT = 19; 276 /** BigDecimal */ 277 static final int ID_BIGDEC = 20; 278 /** Date */ 279 static final int ID_DATE = 21; 280 /** Number */ 281 static final int ID_NUMBER = 22; 282 283 /** First simple type. */ 284 static final int ID_SIMPLE_MIN = 2; 285 /** Last simple type. */ 286 static final int ID_SIMPLE_MAX = 21; 287 /** Last predefined ID, after which dynamic IDs are assigned. */ 288 static final int ID_PREDEFINED = 30; 289 290 static boolean isPredefined(Format format) { 291 return format.getId() <= ID_PREDEFINED; 292 } 293 294 private int id; 295 private String className; 296 private Reader reader; 297 private Format superFormat; 298 private Format latestFormat; 299 private Format previousFormat; 300 private Set<String> supertypes; 301 private boolean deleted; 302 private boolean unused; 303 private transient Catalog catalog; 304 private transient Class type; 305 private transient Format proxiedFormat; 306 private transient boolean initialized; 307 308 /** 309 * Creates a new format for a given class. 310 */ 311 Format(Class type) { 312 this(type.getName()); 313 this.type = type; 314 addSupertypes(); 315 } 316 317 /** 318 * Creates a format for class evolution when no class may be present. 319 */ 320 Format(String className) { 321 this.className = className; 322 latestFormat = this; 323 supertypes = new HashSet<String>(); 324 } 325 326 /** 327 * Special handling for JE 3.0.12 beta formats. 328 */ 329 void migrateFromBeta(Map<String,Format> formatMap) { 330 if (latestFormat == null) { 331 latestFormat = this; 332 } 333 } 334 335 final boolean isNew() { 336 return id == 0; 337 } 338 339 final Catalog getCatalog() { 340 return catalog; 341 } 342 343 /** 344 * Returns the format ID. 345 */ 346 public final int getId() { 347 return id; 348 } 349 350 /** 351 * Called by the Catalog to set the format ID when a new format is added to 352 * the format list, before calling initializeIfNeeded(). 353 */ 354 final void setId(int id) { 355 this.id = id; 356 } 357 358 /** 359 * Returns the class that this format represents. This method will return 360 * null in rawAccess mode, or for an unevolved format. 361 */ 362 final Class getType() { 363 return type; 364 } 365 366 /** 367 * Called to get the type when it is known to exist for an uninitialized 368 * format. 369 */ 370 final Class getExistingType() { 371 if (type == null) { 372 try { 373 type = SimpleCatalog.classForName(className); 374 } catch (ClassNotFoundException e) { 375 throw new IllegalStateException(e); 376 } 377 } 378 return type; 379 } 380 381 /** 382 * Returns the object for reading objects of the latest format. For the 383 * latest version format, 'this' is returned. For prior version formats, a 384 * reader that converts this version to the latest version is returned. 385 */ 386 final Reader getReader() { 387 388 /* 389 * For unit testing, record whether any un-evolved formats are 390 * encountered. 391 */ 392 if (this != reader) { 393 PersistCatalog.unevolvedFormatsEncountered = true; 394 } 395 396 return reader; 397 } 398 399 /** 400 * Changes the reader during format evolution. 401 */ 402 final void setReader(Reader reader) { 403 this.reader = reader; 404 } 405 406 /** 407 * Returns the format of the superclass. 408 */ 409 final Format getSuperFormat() { 410 return superFormat; 411 } 412 413 /** 414 * Called to set the format of the superclass during initialize(). 415 */ 416 final void setSuperFormat(Format superFormat) { 417 this.superFormat = superFormat; 418 } 419 420 /** 421 * Returns the format that is proxied by this format. If non-null is 422 * returned, then this format is a PersistentProxy. 423 */ 424 final Format getProxiedFormat() { 425 return proxiedFormat; 426 } 427 428 /** 429 * Called by ProxiedFormat to set the proxied format. 430 */ 431 final void setProxiedFormat(Format proxiedFormat) { 432 this.proxiedFormat = proxiedFormat; 433 } 434 435 /** 436 * If this is the latest/evolved format, returns this; otherwise, returns 437 * the current version of this format. Note that this WILL return a 438 * format for a deleted class if the latest format happens to be deleted. 439 */ 440 final Format getLatestVersion() { 441 return latestFormat; 442 } 443 444 /** 445 * Returns the previous version of this format in the linked list of 446 * versions, or null if this is the only version. 447 */ 448 public final Format getPreviousVersion() { 449 return previousFormat; 450 } 451 452 /** 453 * Called by Evolver to set the latest format when this old format is 454 * evolved. 455 */ 456 final void setLatestVersion(Format newFormat) { 457 458 /* 459 * If this old format is the former latest version, link it to the new 460 * latest version. This creates a singly linked list of versions 461 * starting with the latest. 462 */ 463 if (latestFormat == this) { 464 newFormat.previousFormat = this; 465 } 466 467 latestFormat = newFormat; 468 } 469 470 /** 471 * Returns whether the class for this format was deleted. 472 */ 473 final boolean isDeleted() { 474 return deleted; 475 } 476 477 /** 478 * Called by the Evolver when applying a Deleter mutation. 479 */ 480 final void setDeleted(boolean deleted) { 481 this.deleted = deleted; 482 } 483 484 /** 485 * Called by the Evolver for a format that is never referenced. 486 */ 487 final void setUnused(boolean unused) { 488 this.unused = unused; 489 } 490 491 /** 492 * Called by the Evolver with true when an entity format or any of its 493 * nested format were changed. Called by Store.evolve when an entity has 494 * been fully converted. Overridden by ComplexFormat. 495 */ 496 void setEvolveNeeded(boolean needed) { 497 throw new UnsupportedOperationException(); 498 } 499 500 /** 501 * Overridden by ComplexFormat. 502 */ 503 boolean getEvolveNeeded() { 504 throw new UnsupportedOperationException(); 505 } 506 507 final boolean isInitialized() { 508 return initialized; 509 } 510 511 /** 512 * Called by the Catalog to initialize a format, and may also be called 513 * during initialize() for a related format to ensure that the related 514 * format is initialized. This latter case is allowed to support 515 * bidirectional dependencies. This method will do nothing if the format 516 * is already intialized. 517 */ 518 final void initializeIfNeeded(Catalog catalog, EntityModel model) { 519 if (!initialized) { 520 initialized = true; 521 this.catalog = catalog; 522 523 /* Initialize objects serialized by an older Format class. */ 524 if (latestFormat == null) { 525 latestFormat = this; 526 } 527 if (reader == null) { 528 reader = this; 529 } 530 531 /* 532 * The class is only guaranteed to be available in live (not raw) 533 * mode, for the current version of the format. 534 */ 535 if (type == null && 536 isCurrentVersion() && 537 (isSimple() || !catalog.isRawAccess())) { 538 getExistingType(); 539 } 540 541 /* Perform subclass-specific initialization. */ 542 initialize(catalog, model, 543 catalog.getInitVersion(this, false /*forReader*/)); 544 reader.initializeReader 545 (catalog, model, 546 catalog.getInitVersion(this, true /*forReader*/), 547 this); 548 } 549 } 550 551 /** 552 * Called to initialize a separate Reader implementation. This method is 553 * called when no separate Reader exists, and does nothing. 554 */ 555 public void initializeReader(Catalog catalog, 556 EntityModel model, 557 int initVersion, 558 Format oldFormat) { 559 } 560 561 /** 562 * Adds all interfaces and superclasses to the supertypes set. 563 */ 564 private void addSupertypes() { 565 addInterfaces(type); 566 Class stype = type.getSuperclass(); 567 while (stype != null && stype != Object.class) { 568 supertypes.add(stype.getName()); 569 addInterfaces(stype); 570 stype = stype.getSuperclass(); 571 } 572 } 573 574 /** 575 * Recursively adds interfaces to the supertypes set. 576 */ 577 private void addInterfaces(Class cls) { 578 Class[] interfaces = cls.getInterfaces(); 579 for (Class iface : interfaces) { 580 if (iface != Enhanced.class) { 581 supertypes.add(iface.getName()); 582 addInterfaces(iface); 583 } 584 } 585 } 586 587 /** 588 * Certain formats (ProxiedFormat for example) prohibit nested fields that 589 * reference the parent object. [#15815] 590 */ 591 boolean areNestedRefsProhibited() { 592 return false; 593 } 594 595 /* -- Start of RawType interface methods. -- */ 596 597 public String getClassName() { 598 return className; 599 } 600 601 public int getVersion() { 602 ClassMetadata meta = getClassMetadata(); 603 if (meta != null) { 604 return meta.getVersion(); 605 } else { 606 return 0; 607 } 608 } 609 610 public Format getSuperType() { 611 return superFormat; 612 } 613 614 /* -- RawType methods that are overridden as needed in subclasses. -- */ 615 616 public boolean isSimple() { 617 return false; 618 } 619 620 public boolean isPrimitive() { 621 return false; 622 } 623 624 public boolean isEnum() { 625 return false; 626 } 627 628 public List<String> getEnumConstants() { 629 return null; 630 } 631 632 public boolean isArray() { 633 return false; 634 } 635 636 public int getDimensions() { 637 return 0; 638 } 639 640 public Format getComponentType() { 641 return null; 642 } 643 644 public Map<String,RawField> getFields() { 645 return null; 646 } 647 648 public ClassMetadata getClassMetadata() { 649 return null; 650 } 651 652 public EntityMetadata getEntityMetadata() { 653 return null; 654 } 655 656 /* -- End of RawType methods. -- */ 657 658 /* -- Methods that may optionally be overridden by subclasses. -- */ 659 660 /** 661 * Called by EntityOutput in rawAccess mode to determine whether an object 662 * type is allowed to be assigned to a given field type. 663 */ 664 boolean isAssignableTo(Format format) { 665 if (proxiedFormat != null) { 666 return proxiedFormat.isAssignableTo(format); 667 } else { 668 return format == this || 669 format.id == ID_OBJECT || 670 supertypes.contains(format.className); 671 } 672 } 673 674 /** 675 * For primitive types only, returns their associated wrapper type. 676 */ 677 Format getWrapperFormat() { 678 return null; 679 } 680 681 /** 682 * Returns whether this format class is an entity class. 683 */ 684 boolean isEntity() { 685 return false; 686 } 687 688 /** 689 * Returns whether this class is present in the EntityModel. Returns false 690 * for a simple type, array type, or enum type. 691 */ 692 boolean isModelClass() { 693 return false; 694 } 695 696 /** 697 * For an entity class or subclass, returns the base entity class; returns 698 * null in other cases. 699 */ 700 ComplexFormat getEntityFormat() { 701 return null; 702 } 703 704 /** 705 * Called for an existing format that may not equal the current format for 706 * the same class. 707 * 708 * <p>If this method returns true, then it must have determined one of two 709 * things: 710 * - that the old and new formats are equal, and it must have called 711 * Evolver.useOldFormat; or 712 * - that the old format can be evolved to the new format, and it must 713 * have called Evolver.useEvolvedFormat.</p> 714 * 715 * <p>If this method returns false, then it must have determined that the 716 * old format could not be evolved to the new format, and it must have 717 * called Evolver.addInvalidMutation, addMissingMutation or 718 * addEvolveError.</p> 719 */ 720 abstract boolean evolve(Format newFormat, Evolver evolver); 721 722 /** 723 * Called when a Converter handles evolution of a class, but we may still 724 * need to evolve the metadata. 725 */ 726 boolean evolveMetadata(Format newFormat, 727 Converter converter, 728 Evolver evolver) { 729 return true; 730 } 731 732 /** 733 * Returns whether this format is the current format for its class. If 734 * false is returned, this format is setup to evolve to the current format. 735 */ 736 final boolean isCurrentVersion() { 737 return latestFormat == this && !deleted; 738 } 739 740 /** 741 * Returns whether this format has the same class as the given format, 742 * irrespective of version changes and renaming. 743 */ 744 final boolean isSameClass(Format other) { 745 return latestFormat == other.latestFormat; 746 } 747 748 /* -- Abstract methods that must be implemented by subclasses. -- */ 749 750 /** 751 * Initializes an uninitialized format, initializing its related formats 752 * (superclass formats and array component formats) first. 753 */ 754 abstract void initialize(Catalog catalog, 755 EntityModel model, 756 int initVersion); 757 758 /** 759 * Calls catalog.createFormat for formats that this format depends on, or 760 * that should also be persistent. 761 */ 762 abstract void collectRelatedFormats(Catalog catalog, 763 Map<String,Format> newFormats); 764 765 /* 766 * The remaining methods are used to read objects from data bytes via 767 * EntityInput, and to write objects as data bytes via EntityOutput. 768 * Ultimately these methods call methods in the Accessor interface to 769 * get/set fields in the object. Most methods have a rawAccess parameter 770 * that determines whether the object is a raw object or a real persistent 771 * object. 772 * 773 * The first group of methods are abstract and must be implemented by 774 * format classes. The second group have default implementations that 775 * throw UnsupportedOperationException and may optionally be overridden. 776 */ 777 778 /** 779 * Creates an array of the format's class of the given length, as if 780 * Array.newInstance(getType(), len) were called. Formats implement this 781 * method for specific classes, or call the accessor, to avoid the 782 * reflection overhead of Array.newInstance. 783 */ 784 abstract Object newArray(int len); 785 786 /** 787 * Creates a new instance of the target class using its default 788 * constructor. Normally this creates an empty object, and readObject() is 789 * called next to fill in the contents. This is done in two steps to allow 790 * the instance to be registered by EntityInput before reading the 791 * contents. This allows the fields in an object or a nested object to 792 * refer to the parent object in a graph. 793 * 794 * Alternatively, this method may read all or the first portion of the 795 * data, rather than that being done by readObject(). This is required for 796 * simple types and enums, where the object cannot be created without 797 * reading the data. In these cases, there is no possibility that the 798 * parent object will be referenced by the child object in the graph. It 799 * should not be done in other cases, or the graph references may not be 800 * maintained faithfully. 801 * 802 * Is public only in order to implement the Reader interface. Note that 803 * this method should only be called directly in raw conversion mode or 804 * during conversion of an old format. Normally it should be called via 805 * the getReader method and the Reader interface. 806 */ 807 public abstract Object newInstance(EntityInput input, boolean rawAccess); 808 809 /** 810 * Called after newInstance() to read the rest of the data bytes and fill 811 * in the object contents. If the object was read completely by 812 * newInstance(), this method does nothing. 813 * 814 * Is public only in order to implement the Reader interface. Note that 815 * this method should only be called directly in raw conversion mode or 816 * during conversion of an old format. Normally it should be called via 817 * the getReader method and the Reader interface. 818 */ 819 public abstract Object readObject(Object o, 820 EntityInput input, 821 boolean rawAccess); 822 823 /** 824 * Writes a given instance of the target class to the output data bytes. 825 * This is the complement of the newInstance()/readObject() pair. 826 */ 827 abstract void writeObject(Object o, EntityOutput output, boolean rawAccess); 828 829 /** 830 * Skips over the object's contents, as if readObject() were called, but 831 * without returning an object. Used for extracting secondary key bytes 832 * without having to instantiate the object. For reference types, the 833 * format ID is read just before calling this method, so this method is 834 * responsible for skipping everything following the format ID. 835 */ 836 abstract void skipContents(RecordInput input); 837 838 /* -- More methods that may optionally be overridden by subclasses. -- */ 839 840 /** 841 * When extracting a secondary key, called to skip over all fields up to 842 * the given secondary key field. Returns the format of the key field 843 * found, or null if the field is not present (nullified) in the object. 844 */ 845 Format skipToSecKey(RecordInput input, String keyName) { 846 throw new UnsupportedOperationException(toString()); 847 } 848 849 /** 850 * Called after skipToSecKey() to copy the data bytes of a singular 851 * (XXX_TO_ONE) key field. 852 */ 853 void copySecKey(RecordInput input, RecordOutput output) { 854 throw new UnsupportedOperationException(toString()); 855 } 856 857 /** 858 * Called after skipToSecKey() to copy the data bytes of an array or 859 * collection (XXX_TO_MANY) key field. 860 */ 861 void copySecMultiKey(RecordInput input, Format keyFormat, Set results) { 862 throw new UnsupportedOperationException(toString()); 863 } 864 865 /** 866 * Nullifies the given key field in the given RawObject -- rawAccess mode 867 * is implied. 868 */ 869 boolean nullifySecKey(Catalog catalog, 870 Object entity, 871 String keyName, 872 Object keyElement) { 873 throw new UnsupportedOperationException(toString()); 874 } 875 876 /** 877 * Returns whether the entity's primary key field is null or zero, as 878 * defined for primary keys that are assigned from a sequence. 879 */ 880 boolean isPriKeyNullOrZero(Object o, boolean rawAccess) { 881 throw new UnsupportedOperationException(toString()); 882 } 883 884 /** 885 * Gets the primary key field from the given object and writes it to the 886 * given output data bytes. This is a separate operation because the 887 * primary key data bytes are stored separately from the rest of the 888 * record. 889 */ 890 void writePriKey(Object o, EntityOutput output, boolean rawAccess) { 891 throw new UnsupportedOperationException(toString()); 892 } 893 894 /** 895 * Reads the primary key from the given input bytes and sets the primary 896 * key field in the given object. This is complement of writePriKey(). 897 * 898 * Is public only in order to implement the Reader interface. Note that 899 * this method should only be called directly in raw conversion mode or 900 * during conversion of an old format. Normally it should be called via 901 * the getReader method and the Reader interface. 902 */ 903 public void readPriKey(Object o, EntityInput input, boolean rawAccess) { 904 throw new UnsupportedOperationException(toString()); 905 } 906 907 /** 908 * Validates and returns the simple integer key format for a sequence key 909 * associated with this format. 910 * 911 * For a composite key type, the format of the one and only field is 912 * returned. For a simple integer type, this format is returned. 913 * Otherwise (the default implementation), an IllegalArgumentException is 914 * thrown. 915 */ 916 Format getSequenceKeyFormat() { 917 throw new IllegalArgumentException 918 ("Type not allowed for sequence: " + getClassName()); 919 } 920 921 /** 922 * Converts a RawObject to a current class object and adds the converted 923 * pair to the converted map. 924 */ 925 Object convertRawObject(Catalog catalog, 926 boolean rawAccess, 927 RawObject rawObject, 928 IdentityHashMap converted) { 929 throw new UnsupportedOperationException(toString()); 930 } 931 932 @Override 933 public String toString() { 934 final String INDENT = " "; 935 final String INDENT2 = INDENT + " "; 936 StringBuffer buf = new StringBuffer(500); 937 if (isSimple()) { 938 addTypeHeader(buf, "SimpleType"); 939 buf.append(" primitive=\""); 940 buf.append(isPrimitive()); 941 buf.append("\"/>\n"); 942 } else if (isEnum()) { 943 addTypeHeader(buf, "EnumType"); 944 buf.append(">\n"); 945 for (String constant : getEnumConstants()) { 946 buf.append(INDENT); 947 buf.append("<Constant>"); 948 buf.append(constant); 949 buf.append("</Constant>\n"); 950 } 951 buf.append("</EnumType>\n"); 952 } else if (isArray()) { 953 addTypeHeader(buf, "ArrayType"); 954 buf.append(" componentId=\""); 955 buf.append(getComponentType().getVersion()); 956 buf.append("\" componentClass=\""); 957 buf.append(getComponentType().getClassName()); 958 buf.append("\" dimensions=\""); 959 buf.append(getDimensions()); 960 buf.append("\"/>\n"); 961 } else { 962 addTypeHeader(buf, "ComplexType"); 963 Format superType = getSuperType(); 964 if (superType != null) { 965 buf.append(" superTypeId=\""); 966 buf.append(superType.getId()); 967 buf.append("\" superTypeClass=\""); 968 buf.append(superType.getClassName()); 969 buf.append('"'); 970 } 971 Format proxiedFormat = getProxiedFormat(); 972 if (proxiedFormat != null) { 973 buf.append(" proxiedTypeId=\""); 974 buf.append(proxiedFormat.getId()); 975 buf.append("\" proxiedTypeClass=\""); 976 buf.append(proxiedFormat.getClassName()); 977 buf.append('"'); 978 } 979 PrimaryKeyMetadata priMeta = null; 980 Map<String,SecondaryKeyMetadata> secondaryKeys = null; 981 List<FieldMetadata> compositeKeyFields = null; 982 ClassMetadata clsMeta = getClassMetadata(); 983 if (clsMeta != null) { 984 compositeKeyFields = clsMeta.getCompositeKeyFields(); 985 priMeta = clsMeta.getPrimaryKey(); 986 secondaryKeys = clsMeta.getSecondaryKeys(); 987 } 988 buf.append(" kind=\""); 989 buf.append(isEntity() ? "entity" : 990 ((compositeKeyFields != null) ? "compositeKey" : 991 "persistent")); 992 buf.append("\">\n"); 993 Map<String, RawField> fields = getFields(); 994 if (fields != null) { 995 for (RawField field : fields.values()) { 996 String name = field.getName(); 997 RawType type = field.getType(); 998 buf.append(INDENT); 999 buf.append("<Field"); 1000 buf.append(" name=\""); 1001 buf.append(name); 1002 buf.append("\" typeId=\""); 1003 buf.append(type.getId()); 1004 buf.append("\" typeClass=\""); 1005 buf.append(type.getClassName()); 1006 buf.append('"'); 1007 if (priMeta != null && 1008 priMeta.getName().equals(name)) { 1009 buf.append(" primaryKey=\"true\""); 1010 if (priMeta.getSequenceName() != null) { 1011 buf.append(" sequence=\""); 1012 buf.append(priMeta.getSequenceName()); 1013 buf.append('"'); 1014 } 1015 } 1016 if (secondaryKeys != null) { 1017 SecondaryKeyMetadata secMeta = 1018 ComplexFormat.getSecondaryKeyMetadataByFieldName 1019 (secondaryKeys, name); 1020 if (secMeta != null) { 1021 buf.append(" secondaryKey=\"true\" keyName=\""); 1022 buf.append(secMeta.getKeyName()); 1023 buf.append("\" relate=\""); 1024 buf.append(secMeta.getRelationship()); 1025 buf.append('"'); 1026 String related = secMeta.getRelatedEntity(); 1027 if (related != null) { 1028 buf.append("\" relatedEntity=\""); 1029 buf.append(related); 1030 buf.append("\" onRelatedEntityDelete=\""); 1031 buf.append(secMeta.getDeleteAction()); 1032 buf.append('"'); 1033 } 1034 } 1035 } 1036 if (compositeKeyFields != null) { 1037 int nFields = compositeKeyFields.size(); 1038 for (int i = 0; i < nFields; i += 1) { 1039 FieldMetadata fldMeta = compositeKeyFields.get(i); 1040 if (fldMeta.getName().equals(name)) { 1041 buf.append(" compositeKeyField=\""); 1042 buf.append(i + 1); 1043 buf.append('"'); 1044 } 1045 } 1046 } 1047 buf.append("/>\n"); 1048 } 1049 EntityMetadata entMeta = getEntityMetadata(); 1050 if (entMeta != null) { 1051 buf.append(INDENT); 1052 buf.append("<EntityKeys>\n"); 1053 priMeta = entMeta.getPrimaryKey(); 1054 if (priMeta != null) { 1055 buf.append(INDENT2); 1056 buf.append("<Primary class=\""); 1057 buf.append(priMeta.getDeclaringClassName()); 1058 buf.append("\" field=\""); 1059 buf.append(priMeta.getName()); 1060 buf.append("\"/>\n"); 1061 } 1062 secondaryKeys = entMeta.getSecondaryKeys(); 1063 if (secondaryKeys != null) { 1064 for (SecondaryKeyMetadata secMeta : 1065 secondaryKeys.values()) { 1066 buf.append(INDENT2); 1067 buf.append("<Secondary class=\""); 1068 buf.append(secMeta.getDeclaringClassName()); 1069 buf.append("\" field=\""); 1070 buf.append(secMeta.getName()); 1071 buf.append("\"/>\n"); 1072 } 1073 } 1074 buf.append("</EntityKeys>\n"); 1075 } 1076 } 1077 buf.append("</ComplexType>\n"); 1078 } 1079 return buf.toString(); 1080 } 1081 1082 private void addTypeHeader(StringBuffer buf, String elemName) { 1083 buf.append('<'); 1084 buf.append(elemName); 1085 buf.append(" id=\""); 1086 buf.append(getId()); 1087 buf.append("\" class=\""); 1088 buf.append(getClassName()); 1089 buf.append("\" version=\""); 1090 buf.append(getVersion()); 1091 buf.append('"'); 1092 Format currVersion = getLatestVersion(); 1093 if (currVersion != null) { 1094 buf.append(" currentVersionId=\""); 1095 buf.append(currVersion.getId()); 1096 buf.append('"'); 1097 } 1098 Format prevVersion = getPreviousVersion(); 1099 if (prevVersion != null) { 1100 buf.append(" previousVersionId=\""); 1101 buf.append(prevVersion.getId()); 1102 buf.append('"'); 1103 } 1104 } 1105} 1106