KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sleepycat > persist > impl > Format


1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 2002,2006 Oracle. All rights reserved.
5  *
6  * $Id: Format.java,v 1.29 2006/10/30 21:14:32 bostic Exp $
7  */

8
9 package com.sleepycat.persist.impl;
10
11 import java.io.Serializable JavaDoc;
12 import java.util.HashSet JavaDoc;
13 import java.util.IdentityHashMap JavaDoc;
14 import java.util.List JavaDoc;
15 import java.util.Map JavaDoc;
16 import java.util.Set JavaDoc;
17
18 import com.sleepycat.persist.evolve.Converter;
19 import com.sleepycat.persist.model.ClassMetadata;
20 import com.sleepycat.persist.model.EntityMetadata;
21 import com.sleepycat.persist.raw.RawField;
22 import com.sleepycat.persist.raw.RawObject;
23 import com.sleepycat.persist.raw.RawType;
24
25 /**
26  * The base class for all object formats. Formats are used to define the
27  * stored layout for all persistent classes, including simple types.
28  *
29  * The design documentation below describes the storage format for entities and
30  * its relationship to information stored per format in the catalog.
31  *
32  * Requirements
33  * ------------
34  * + Provides EntityBinding for objects and EntryBinding for keys.
35  * + Provides SecondaryKeyCreator, SecondaryMultiKeyCreator and
36  * SecondaryMultiKeyNullifier (SecondaryKeyNullifier is redundant).
37  * + Works with reflection and bytecode enhancement.
38  * + For reflection only, works with any entity model not just annotations.
39  * + Bindings are usable independently of the persist API.
40  * + Performance is almost equivalent to hand coded tuple bindings.
41  * + Small performance penalty for compatible class changes (new fields,
42  * widening).
43  * + Secondary key create/nullify do not have to deserialize the entire record;
44  * in other words, store secondary keys at the start of the data.
45  *
46  * Class Format
47  * ------------
48  * Every distinct class format is given a unique format ID. Class IDs are not
49  * equivalent to class version numbers (as in the version property of @Entity
50  * and @Persistent) because the format can change when the version number does
51  * not. Changes that cause a unique format ID to be assigned are:
52  *
53  * + Add field.
54  * + Widen field type.
55  * + Change primitive type to primitive wrapper class.
56  * + Add or drop secondary key.
57  * + Any incompatible class change.
58  *
59  * The last item, incompatible class changes, also correspond to a class
60  * version change.
61  *
62  * For each distinct class format the following information is conceptually
63  * stored in the catalog, keyed by format ID.
64  *
65  * - Class name
66  * - Class version number
67  * - Superclass format
68  * - Kind: simple, enum, complex, array
69  * - For kind == simple:
70  * - Primitive class
71  * - For kind == enum:
72  * - Array of constant names, sorted by name.
73  * - For kind == complex:
74  * - Primary key fieldInfo, or null if no primary key is declared
75  * - Array of secondary key fieldInfo, sorted by field name
76  * - Array of other fieldInfo, sorted by field name
77  * - For kind == array:
78  * - Component class format
79  * - Number of array dimensions
80  * - Other metadata for RawType
81  *
82  * Where fieldInfo is:
83  * - Field name
84  * - Field class
85  * - Other metadata for RawField
86  *
87  * Data Layout
88  * -----------
89  * For each entity instance the data layout is as follows:
90  *
91  * instanceData: formatId keyFields... nonKeyFields...
92  * keyFields: fieldValue...
93  * nonKeyFields: fieldValue...
94  *
95  * The formatId is the (positive non-zero) ID of a class format, defined above.
96  * This is ID of the most derived class of the instance. It is stored as a
97  * packed integer.
98  *
99  * Following the format ID, zero or more sets of secondary key field values
100  * appear, followed by zero or more sets of other class field values.
101  *
102  * The keyFields are the sets of secondary key fields for each class in order
103  * of the highest superclass first. Within a class, fields are ordered by
104  * field name.
105  *
106  * The nonKeyFields are the sets of other non-key fields for each class in
107  * order of the highest superclass first. Within a class, fields are ordered
108  * by field name.
109  *
110  * A field value is:
111  *
112  * fieldValue: primitiveValue
113  * | nullId
114  * | instanceRef
115  * | instanceData
116  * | simpleValue
117  * | enumValue
118  * | arrayValue
119  *
120  * For a primitive type, a primitive value is used as defined for tuple
121  * bindings. For float and double, sorted float and sorted double tuple values
122  * are used.
123  *
124  * For a non-primitive type with a null value, a nullId is used that has a zero
125  * (illegal formatId) value. This includes String and other simple reference
126  * types. The formatId is stored as a packed integer, meaning that it is
127  * stored as a single zero byte.
128  *
129  * For a non-primitive type, an instanceRef is used for a non-null instance
130  * that appears earlier in the data byte array. An instanceRef is the negation
131  * of the byte offset of the instanceData that appears earlier. It is stored
132  * as a packed integer.
133  *
134  * The remaining rules apply only to reference types with non-null values that
135  * do not appear earlier in the data array.
136  *
137  * For an array type, an array formatId is used that identifies the component
138  * type and the number of array dimensions. This is followed by an array
139  * length (stored as a packed integer) and zero or more fieldValue elements.
140  * For an array with N+1 dimensions where N is greater than zero, the leftmost
141  * dimension is enumerated such that each fieldValue element is itself an array
142  * of N dimensions or null.
143  *
144  * arrayValue: formatId length fieldValue...
145  *
146  * For an enum type, an enumValue is used, consisting of a formatId that
147  * identifies the enum class and an enumIndex (stored as a packed integer) that
148  * identifies the constant name in the enum constant array of the enum class
149  * format:
150  *
151  * enumValue: formatId enumIndex
152  *
153  * For a simple type, a simpleValue is used. This consists of the formatId
154  * that identifies the class followed by the simple type value. For a
155  * primitive wrapper type the simple type value is the corresponding primitive,
156  * for a Date it is the milliseconds as a long primitive, and for BigInteger or
157  * BigDecimal it is a byte array as defined for tuple bindings of these types.
158  *
159  * simpleValue: formatId value
160  *
161  * For all other complex types, an instanceData is used, which is defined
162  * above.
163  *
164  * Secondary Keys
165  * --------------
166  * For secondary key support we must account for writing and nullifying
167  * specific keys. Rather than instantiating the entity and then performing
168  * the secondary key operation, we strive to perform the secondary key
169  * operation directly on the byte format.
170  *
171  * To create a secondary key we skip over other fields and then copy the bytes
172  * of the embedded key. This approach is very efficient because a) the entity
173  * is not instantiated, and b) the secondary keys are stored at the beginning
174  * of the byte format and can be quickly read.
175  *
176  * To nullify we currently instantiate the raw entity, set the key field to null
177  * (or remove it from the array/collection), and convert the raw entity back to
178  * bytes. Although the performance of this approach is not ideal because it
179  * requires serialization, it avoids the complexity of modifying the packed
180  * serialized format directly, adjusting references to key objects, etc. Plus,
181  * when we nullify a key we are going to write the record, so the serialization
182  * overhead may not be significant. For the record, I tried implementing
183  * nullification of the bytes directly and found it was much too complex.
184  *
185  * Lifecycle
186  * ---------
187  * Format are managed by a Catalog class. Simple formats are managed by
188  * SimpleCatalog, and are copied from the SimpleCatalog by PersistCatalog.
189  * Other formats are managed by PersistCatalog. The lifecycle of a format
190  * instance is:
191  *
192  * - Constructed by the catalog when a format is requested for a Class
193  * that currently has no associated format.
194  *
195  * - The catalog calls setId() and adds the format to its format list
196  * (indexed by format id) and map (keyed by class name).
197  *
198  * - The catalog calls collectRelatedFormats(), where a format can create
199  * additional formats that it needs, or that should also be persistent.
200  *
201  * - The catalog calls initializeIfNeeded(), which calls the initialize()
202  * method of the format class.
203  *
204  * - initialize() should initialize any transient fields in the format.
205  * initialize() can assume that all related formats are available in the
206  * catalog. It may call initializeIfNeeded() for those related formats, if
207  * it needs to interact with an initialized related format; this does not
208  * cause a cycle, because initializeIfNeeded() does nothing for an already
209  * initialized format.
210  *
211  * - The catalog creates a group of related formats at one time, and then
212  * writes its entire list of formats to the catalog DB as a single record.
213  * This grouping reduces the number of writes.
214  *
215  * - When a catalog is opened and the list of existing formats is read. After
216  * a format is deserialized, its initializeIfNeeded() method is called.
217  * setId() and collectRelatedFormats() are not called, since the ID and
218  * related formats are stored in serialized fields.
219  *
220  * - There are two modes for opening an existing catalog: raw mode and normal
221  * mode. In raw mode, the old format is used regardless of whether it
222  * matches the current class definition; in fact the class is not accessed
223  * and does not need to be present.
224  *
225  * - In normal mode, for each existing format that is initialized, a new format
226  * is also created based on the current class and metadata definition. If
227  * the two formats are equal, the new format is discarded. If they are
228  * unequal, the new format becomes the current format and the old format's
229  * evolve() method is called. evolve() is responsible for adjusting the
230  * old format for class evolution. Any number of non-current formats may
231  * exist for a given class, and are setup to evolve the single current format
232  * for the class.
233  *
234  * @author Mark Hayes
235  */

236 public abstract class Format implements Reader, RawType, Serializable JavaDoc {
237
238     private static final long serialVersionUID = 545633644568489850L;
239
240     /** Null reference. */
241     static final int ID_NULL = 0;
242     /** Object */
243     static final int ID_OBJECT = 1;
244     /** Boolean */
245     static final int ID_BOOL = 2;
246     static final int ID_BOOL_W = 3;
247     /** Byte */
248     static final int ID_BYTE = 4;
249     static final int ID_BYTE_W = 5;
250     /** Short */
251     static final int ID_SHORT = 6;
252     static final int ID_SHORT_W = 7;
253     /** Integer */
254     static final int ID_INT = 8;
255     static final int ID_INT_W = 9;
256     /** Long */
257     static final int ID_LONG = 10;
258     static final int ID_LONG_W = 11;
259     /** Float */
260     static final int ID_FLOAT = 12;
261     static final int ID_FLOAT_W = 13;
262     /** Double */
263     static final int ID_DOUBLE = 14;
264     static final int ID_DOUBLE_W = 15;
265     /** Character */
266     static final int ID_CHAR = 16;
267     static final int ID_CHAR_W = 17;
268     /** String */
269     static final int ID_STRING = 18;
270     /** BigInteger */
271     static final int ID_BIGINT = 19;
272     /** BigDecimal */
273     static final int ID_BIGDEC = 20;
274     /** Date */
275     static final int ID_DATE = 21;
276     /** Number */
277     static final int ID_NUMBER = 22;
278
279     /** First simple type. */
280     static final int ID_SIMPLE_MIN = 2;
281     /** Last simple type. */
282     static final int ID_SIMPLE_MAX = 21;
283     /** Last predefined ID, after which dynamic IDs are assigned. */
284     static final int ID_PREDEFINED = 30;
285
286     static boolean isPredefined(Format format) {
287         return format.getId() <= ID_PREDEFINED;
288     }
289
290     private int id;
291     private String JavaDoc className;
292     private Reader reader;
293     private Format superFormat;
294     private Format latestFormat;
295     private Format previousFormat;
296     private Set JavaDoc<String JavaDoc> supertypes;
297     private boolean deleted;
298     private boolean unused;
299     private transient Catalog catalog;
300     private transient Class JavaDoc type;
301     private transient Format proxiedFormat;
302     private transient boolean initialized;
303
304     /**
305      * Creates a new format for a given class.
306      */

307     Format(Class JavaDoc type) {
308         this(type.getName());
309         this.type = type;
310         addSupertypes();
311     }
312
313     /**
314      * Creates a format for class evolution when no class may be present.
315      */

316     Format(String JavaDoc className) {
317         this.className = className;
318         latestFormat = this;
319         supertypes = new HashSet JavaDoc<String JavaDoc>();
320     }
321
322     /**
323      * Special handling for JE 3.0.12 beta formats.
324      */

325     void migrateFromBeta(Map JavaDoc<String JavaDoc,Format> formatMap) {
326         if (latestFormat == null) {
327             latestFormat = this;
328         }
329     }
330
331     final boolean isNew() {
332         return id == 0;
333     }
334
335     final Catalog getCatalog() {
336         return catalog;
337     }
338
339     /**
340      * Returns the format ID.
341      */

342     final int getId() {
343         return id;
344     }
345
346     /**
347      * Called by the Catalog to set the format ID when a new format is added to
348      * the format list, before calling initializeIfNeeded().
349      */

350     final void setId(int id) {
351         this.id = id;
352     }
353
354     /**
355      * Returns the class that this format represents. This method will return
356      * null in rawAccess mode, or for an unevolved format.
357      */

358     final Class JavaDoc getType() {
359         return type;
360     }
361
362     /**
363      * Called to get the type when it is known to exist for an uninitialized
364      * format.
365      */

366     final Class JavaDoc getExistingType() {
367         if (type == null) {
368             try {
369                 type = SimpleCatalog.classForName(className);
370             } catch (ClassNotFoundException JavaDoc e) {
371                 throw new IllegalStateException JavaDoc(e);
372             }
373         }
374         return type;
375     }
376
377     /**
378      * Returns the object for reading objects of the latest format. For the
379      * latest version format, 'this' is returned. For prior version formats, a
380      * reader that converts this version to the latest version is returned.
381      */

382     final Reader getReader() {
383         return reader;
384     }
385
386     /**
387      * Changes the reader during format evolution.
388      */

389     final void setReader(Reader reader) {
390         this.reader = reader;
391     }
392
393     /**
394      * Returns the format of the superclass.
395      */

396     final Format getSuperFormat() {
397         return superFormat;
398     }
399
400     /**
401      * Called to set the format of the superclass during initialize().
402      */

403     final void setSuperFormat(Format superFormat) {
404         this.superFormat = superFormat;
405     }
406
407     /**
408      * Returns the format that is proxied by this format. If non-null is
409      * returned, then this format is a PersistentProxy.
410      */

411     final Format getProxiedFormat() {
412         return proxiedFormat;
413     }
414
415     /**
416      * Called by ProxiedFormat to set the proxied format.
417      */

418     final void setProxiedFormat(Format proxiedFormat) {
419         this.proxiedFormat = proxiedFormat;
420     }
421
422     /**
423      * If this is the latest/evolved format, returns this; otherwise, returns
424      * the current version of this format. Note that this WILL return a
425      * format for a deleted class if the latest format happens to be deleted.
426      */

427     final Format getLatestVersion() {
428         return latestFormat;
429     }
430
431     /**
432      * Returns the previous version of this format in the linked list of
433      * versions, or null if this is the only version.
434      */

435     public final Format getPreviousVersion() {
436         return previousFormat;
437     }
438
439     /**
440      * Called by Evolver to set the latest format when this old format is
441      * evolved.
442      */

443     final void setLatestVersion(Format newFormat) {
444
445         /*
446          * If this old format is the former latest version, link it to the new
447          * latest version. This creates a singly linked list of versions
448          * starting with the latest.
449          */

450         if (latestFormat == this) {
451             newFormat.previousFormat = this;
452         }
453
454         latestFormat = newFormat;
455     }
456
457     /**
458      * Returns whether the class for this format was deleted.
459      */

460     final boolean isDeleted() {
461         return deleted;
462     }
463
464     /**
465      * Called by the Evolver when applying a Deleter mutation.
466      */

467     final void setDeleted(boolean deleted) {
468         this.deleted = deleted;
469     }
470
471     /**
472      * Called by the Evolver for a format that is never referenced.
473      */

474     final void setUnused(boolean unused) {
475         this.unused = unused;
476     }
477
478     /**
479      * Called by the Evolver with true when an entity format or any of its
480      * nested format were changed. Called by Store.evolve when an entity has
481      * been fully converted. Overridden by ComplexFormat.
482      */

483     void setEvolveNeeded(boolean needed) {
484         throw new UnsupportedOperationException JavaDoc();
485     }
486
487     /**
488      * Overridden by ComplexFormat.
489      */

490     boolean getEvolveNeeded() {
491         throw new UnsupportedOperationException JavaDoc();
492     }
493
494     final boolean isInitialized() {
495         return initialized;
496     }
497
498     /**
499      * Called by the Catalog to initialize a format, and may also be called
500      * during initialize() for a related format to ensure that the related
501      * format is initialized. This latter case is allowed to support
502      * bidirectional dependencies. This method will do nothing if the format
503      * is already intialized.
504      */

505     final void initializeIfNeeded(Catalog catalog) {
506         if (!initialized) {
507             initialized = true;
508             this.catalog = catalog;
509
510             /* Initialize objects serialized by an older Format class. */
511             if (latestFormat == null) {
512                 latestFormat = this;
513             }
514             if (reader == null) {
515                 reader = this;
516             }
517
518             /*
519              * The class is only guaranteed to be available in live (not raw)
520              * mode, for the current version of the format.
521              */

522             if (type == null &&
523                 isCurrentVersion() &&
524                 (isSimple() || !catalog.isRawAccess())) {
525                 getExistingType();
526             }
527
528             /* Perform subclass-specific initialization. */
529             initialize(catalog);
530             reader.initializeReader(catalog, this);
531         }
532     }
533
534     /**
535      * Called to initialize a separate Reader implementation. This method is
536      * called when no separate Reader exists, and does nothing.
537      */

538     public void initializeReader(Catalog catalog, Format oldFormat) {
539     }
540
541     /**
542      * Adds all interfaces and superclasses to the supertypes set.
543      */

544     private void addSupertypes() {
545         addInterfaces(type);
546         Class JavaDoc stype = type.getSuperclass();
547         while (stype != null && stype != Object JavaDoc.class) {
548             supertypes.add(stype.getName());
549             addInterfaces(stype);
550             stype = stype.getSuperclass();
551         }
552     }
553
554     /**
555      * Recursively adds interfaces to the supertypes set.
556      */

557     private void addInterfaces(Class JavaDoc cls) {
558         Class JavaDoc[] interfaces = cls.getInterfaces();
559         for (Class JavaDoc iface : interfaces) {
560             if (iface != Enhanced.class) {
561                 supertypes.add(iface.getName());
562                 addInterfaces(iface);
563             }
564         }
565     }
566
567     /* -- Start of RawType interface methods. -- */
568
569     public String JavaDoc getClassName() {
570         return className;
571     }
572
573     public int getVersion() {
574         ClassMetadata meta = getClassMetadata();
575         if (meta != null) {
576             return meta.getVersion();
577         } else {
578             return 0;
579         }
580     }
581
582     public Format getSuperType() {
583         return superFormat;
584     }
585
586     /* -- RawType methods that are overridden as needed in subclasses. -- */
587
588     public boolean isSimple() {
589         return false;
590     }
591
592     public boolean isPrimitive() {
593         return false;
594     }
595
596     public boolean isEnum() {
597         return false;
598     }
599
600     public List JavaDoc<String JavaDoc> getEnumConstants() {
601         return null;
602     }
603
604     public boolean isArray() {
605         return false;
606     }
607
608     public int getDimensions() {
609         return 0;
610     }
611
612     public Format getComponentType() {
613         return null;
614     }
615
616     public Map JavaDoc<String JavaDoc,RawField> getFields() {
617         return null;
618     }
619
620     /* -- End of RawType methods. -- */
621
622     /* -- Methods that may optionally be overridden by subclasses. -- */
623
624     /**
625      * Called by EntityOutput in rawAccess mode to determine whether an object
626      * type is allowed to be assigned to a given field type.
627      */

628     boolean isAssignableTo(Format format) {
629         if (proxiedFormat != null) {
630             return proxiedFormat.isAssignableTo(format);
631         } else {
632             return format == this ||
633                    format.id == ID_OBJECT ||
634                    supertypes.contains(format.className);
635         }
636     }
637
638     /**
639      * For primitive types only, returns their associated wrapper type.
640      */

641     Format getWrapperFormat() {
642         return null;
643     }
644
645     /**
646      * Returns whether this format class is an entity class.
647      */

648     boolean isEntity() {
649         return false;
650     }
651
652     /**
653      * Returns whether this class is present in the EntityModel. Returns false
654      * for a simple type, array type, or enum type.
655      */

656     boolean isModelClass() {
657         return false;
658     }
659
660     /**
661      * Returns the original model class metadata used to create this class, or
662      * null if this is not a model class.
663      */

664     ClassMetadata getClassMetadata() {
665         return null;
666     }
667
668     /**
669      * Returns the original model entity metadata used to create this class, or
670      * null if this is not an entity class.
671      */

672     EntityMetadata getEntityMetadata() {
673         return null;
674     }
675
676     /**
677      * For an entity class or subclass, returns the base entity class; returns
678      * null in other cases.
679      */

680     Format getEntityFormat() {
681         return null;
682     }
683
684     /**
685      * Called for an existing format that may not equal the current format for
686      * the same class.
687      *
688      * <p>If this method returns true, then it must have determined that the
689      * old and new formats are equal, and it must have called either
690      * Evolver.useOldFormat or useEvolvedFormat. If this method returns false,
691      * then it must have determined that the old format could not be evolved to
692      * the new format, and it must have called Evolver.addInvalidMutation,
693      * addMissingMutation or addEvolveError.</p>
694      */

695     abstract boolean evolve(Format newFormat, Evolver evolver);
696
697     /**
698      * Called when a Converter handles evolution of a class, but we may still
699      * need to evolve the metadata.
700      */

701     boolean evolveMetadata(Format newFormat,
702                            Converter converter,
703                            Evolver evolver) {
704         return true;
705     }
706
707     /**
708      * Returns whether this format is the current format for its class. If
709      * false is returned, this format is setup to evolve to the current format.
710      */

711     final boolean isCurrentVersion() {
712         return latestFormat == this && !deleted;
713     }
714
715     /**
716      * Returns whether this format has the same class as the given format,
717      * irrespective of version changes and renaming.
718      */

719     final boolean isSameClass(Format other) {
720         return latestFormat == other.latestFormat;
721     }
722
723     /* -- Abstract methods that must be implemented by subclasses. -- */
724
725     /**
726      * Initializes an uninitialized format, initializing its related formats
727      * (superclass formats and array component formats) first.
728      */

729     abstract void initialize(Catalog catalog);
730
731     /**
732      * Calls catalog.createFormat for formats that this format depends on, or
733      * that should also be persistent.
734      */

735     abstract void collectRelatedFormats(Catalog catalog,
736                                         Map JavaDoc<String JavaDoc,Format> newFormats);
737
738     /*
739      * The remaining methods are used to read objects from data bytes via
740      * EntityInput, and to write objects as data bytes via EntityOutput.
741      * Ultimately these methods call methods in the Accessor interface to
742      * get/set fields in the object. Most methods have a rawAccess parameter
743      * that determines whether the object is a raw object or a real persistent
744      * object.
745      *
746      * The first group of methods are abstract and must be implemented by
747      * format classes. The second group have default implementations that
748      * throw UnsupportedOperationException and may optionally be overridden.
749      */

750     
751     /**
752      * Creates an array of the format's class of the given length, as if
753      * Array.newInstance(getType(), len) were called. Formats implement this
754      * method for specific classes, or call the accessor, to avoid the
755      * reflection overhead of Array.newInstance.
756      */

757     abstract Object JavaDoc newArray(int len);
758
759     /**
760      * Creates a new instance of the target class using its default
761      * constructor. Normally this creates an empty object, and readObject() is
762      * called next to fill in the contents. This is done in two steps to allow
763      * the instance to be registered by EntityInput before reading the
764      * contents. This allows the fields in an object or a nested object to
765      * refer to the parent object in a graph.
766      *
767      * Alternatively, this method may read all or the first portion of the
768      * data, rather than that being done by readObject(). This is required for
769      * simple types and enums, where the object cannot be created without
770      * reading the data. In these cases, there is no possibility that the
771      * parent object will be referenced by the child object in the graph. It
772      * should not be done in other cases, or the graph references may not be
773      * maintained faithfully.
774      *
775      * Is public only in order to implement the Reader interface. Note that
776      * this method should only be called directly in raw conversion mode or
777      * during conversion of an old format. Normally it should be called via
778      * the getReader method and the Reader interface.
779      */

780     public abstract Object JavaDoc newInstance(EntityInput input, boolean rawAccess);
781
782     /**
783      * Called after newInstance() to read the rest of the data bytes and fill
784      * in the object contents. If the object was read completely by
785      * newInstance(), this method does nothing.
786      *
787      * Is public only in order to implement the Reader interface. Note that
788      * this method should only be called directly in raw conversion mode or
789      * during conversion of an old format. Normally it should be called via
790      * the getReader method and the Reader interface.
791      */

792     public abstract Object JavaDoc readObject(Object JavaDoc o,
793                                       EntityInput input,
794                                       boolean rawAccess);
795
796     /**
797      * Writes a given instance of the target class to the output data bytes.
798      * This is the complement of the newInstance()/readObject() pair.
799      */

800     abstract void writeObject(Object JavaDoc o, EntityOutput output, boolean rawAccess);
801
802     /**
803      * Skips over the object's contents, as if readObject() were called, but
804      * without returning an object. Used for extracting secondary key bytes
805      * without having to instantiate the object. For reference types, the
806      * format ID is read just before calling this method, so this method is
807      * responsible for skipping everything following the format ID.
808      */

809     abstract void skipContents(RecordInput input);
810
811     /* -- More methods that may optionally be overridden by subclasses. -- */
812
813     /**
814      * When extracting a secondary key, called to skip over all fields up to
815      * the given secondary key field. Returns the format of the key field
816      * found, or null if the field is not present (nullified) in the object.
817      */

818     Format skipToSecKey(RecordInput input, String JavaDoc keyName) {
819         throw new UnsupportedOperationException JavaDoc(toString());
820     }
821
822     /**
823      * Called after skipToSecKey() to copy the data bytes of a singular
824      * (XXX_TO_ONE) key field.
825      */

826     void copySecKey(RecordInput input, RecordOutput output) {
827         throw new UnsupportedOperationException JavaDoc(toString());
828     }
829
830     /**
831      * Called after skipToSecKey() to copy the data bytes of an array or
832      * collection (XXX_TO_MANY) key field.
833      */

834     void copySecMultiKey(RecordInput input, Format keyFormat, Set JavaDoc results) {
835         throw new UnsupportedOperationException JavaDoc(toString());
836     }
837
838     /**
839      * Nullifies the given key field in the given RawObject -- rawAccess mode
840      * is implied.
841      */

842     boolean nullifySecKey(Catalog catalog,
843                           Object JavaDoc entity,
844                           String JavaDoc keyName,
845                           Object JavaDoc keyElement) {
846         throw new UnsupportedOperationException JavaDoc(toString());
847     }
848
849     /**
850      * Returns whether the entity's primary key field is null or zero, as
851      * defined for primary keys that are assigned from a sequence.
852      */

853     boolean isPriKeyNullOrZero(Object JavaDoc o, boolean rawAccess) {
854         throw new UnsupportedOperationException JavaDoc(toString());
855     }
856
857     /**
858      * Gets the primary key field from the given object and writes it to the
859      * given output data bytes. This is a separate operation because the
860      * primary key data bytes are stored separately from the rest of the
861      * record.
862      */

863     void writePriKey(Object JavaDoc o, EntityOutput output, boolean rawAccess) {
864         throw new UnsupportedOperationException JavaDoc(toString());
865     }
866
867     /**
868      * Reads the primary key from the given input bytes and sets the primary
869      * key field in the given object. This is complement of writePriKey().
870      *
871      * Is public only in order to implement the Reader interface. Note that
872      * this method should only be called directly in raw conversion mode or
873      * during conversion of an old format. Normally it should be called via
874      * the getReader method and the Reader interface.
875      */

876     public void readPriKey(Object JavaDoc o, EntityInput input, boolean rawAccess) {
877         throw new UnsupportedOperationException JavaDoc(toString());
878     }
879
880     /**
881      * Converts a RawObject to a current class object and adds the converted
882      * pair to the converted map.
883      */

884     Object JavaDoc convertRawObject(Catalog catalog,
885                             boolean rawAccess,
886                             RawObject rawObject,
887                             IdentityHashMap JavaDoc converted) {
888         throw new UnsupportedOperationException JavaDoc(toString());
889     }
890
891     @Override JavaDoc
892     public String JavaDoc toString() {
893         return "[RawType class: " + getClassName() +
894                " version: " + getVersion() +
895                " internal: " + getClass().getName() +
896                ((reader != null) ?
897                    (" reader: " + reader.getClass().getName()) : "") +
898                ']';
899     }
900 }
901
Popular Tags