1/*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 2002,2008 Oracle.  All rights reserved.
5 *
6 * $Id: Format.java,v 1.1 2008/02/07 17:12:27 mark Exp $
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.raw.RawField;
22import com.sleepycat.persist.raw.RawObject;
23import 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 */
236public abstract class Format implements Reader, RawType, Serializable {
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 className;
292    private Reader reader;
293    private Format superFormat;
294    private Format latestFormat;
295    private Format previousFormat;
296    private Set<String> supertypes;
297    private boolean deleted;
298    private boolean unused;
299    private transient Catalog catalog;
300    private transient Class 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 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 className) {
317        this.className = className;
318        latestFormat = this;
319        supertypes = new HashSet<String>();
320    }
321
322    /**
323     * Special handling for JE 3.0.12 beta formats.
324     */
325    void migrateFromBeta(Map<String,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 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 getExistingType() {
367        if (type == null) {
368            try {
369                type = SimpleCatalog.classForName(className);
370            } catch (ClassNotFoundException e) {
371                throw new IllegalStateException(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
384        /*
385         * For unit testing, record whether any un-evolved formats are
386         * encountered.
387         */
388        if (this != reader) {
389            PersistCatalog.unevolvedFormatsEncountered = true;
390        }
391
392        return reader;
393    }
394
395    /**
396     * Changes the reader during format evolution.
397     */
398    final void setReader(Reader reader) {
399        this.reader = reader;
400    }
401
402    /**
403     * Returns the format of the superclass.
404     */
405    final Format getSuperFormat() {
406        return superFormat;
407    }
408
409    /**
410     * Called to set the format of the superclass during initialize().
411     */
412    final void setSuperFormat(Format superFormat) {
413        this.superFormat = superFormat;
414    }
415
416    /**
417     * Returns the format that is proxied by this format.  If non-null is
418     * returned, then this format is a PersistentProxy.
419     */
420    final Format getProxiedFormat() {
421        return proxiedFormat;
422    }
423
424    /**
425     * Called by ProxiedFormat to set the proxied format.
426     */
427    final void setProxiedFormat(Format proxiedFormat) {
428        this.proxiedFormat = proxiedFormat;
429    }
430
431    /**
432     * If this is the latest/evolved format, returns this; otherwise, returns
433     * the current version of this format.  Note that this WILL return a
434     * format for a deleted class if the latest format happens to be deleted.
435     */
436    final Format getLatestVersion() {
437        return latestFormat;
438    }
439
440    /**
441     * Returns the previous version of this format in the linked list of
442     * versions, or null if this is the only version.
443     */
444    public final Format getPreviousVersion() {
445        return previousFormat;
446    }
447
448    /**
449     * Called by Evolver to set the latest format when this old format is
450     * evolved.
451     */
452    final void setLatestVersion(Format newFormat) {
453
454        /*
455         * If this old format is the former latest version, link it to the new
456         * latest version.  This creates a singly linked list of versions
457         * starting with the latest.
458         */
459        if (latestFormat == this) {
460            newFormat.previousFormat = this;
461        }
462
463        latestFormat = newFormat;
464    }
465
466    /**
467     * Returns whether the class for this format was deleted.
468     */
469    final boolean isDeleted() {
470        return deleted;
471    }
472
473    /**
474     * Called by the Evolver when applying a Deleter mutation.
475     */
476    final void setDeleted(boolean deleted) {
477        this.deleted = deleted;
478    }
479
480    /**
481     * Called by the Evolver for a format that is never referenced.
482     */
483    final void setUnused(boolean unused) {
484        this.unused = unused;
485    }
486
487    /**
488     * Called by the Evolver with true when an entity format or any of its
489     * nested format were changed.  Called by Store.evolve when an entity has
490     * been fully converted.  Overridden by ComplexFormat.
491     */
492    void setEvolveNeeded(boolean needed) {
493        throw new UnsupportedOperationException();
494    }
495
496    /**
497     * Overridden by ComplexFormat.
498     */
499    boolean getEvolveNeeded() {
500        throw new UnsupportedOperationException();
501    }
502
503    final boolean isInitialized() {
504        return initialized;
505    }
506
507    /**
508     * Called by the Catalog to initialize a format, and may also be called
509     * during initialize() for a related format to ensure that the related
510     * format is initialized.  This latter case is allowed to support
511     * bidirectional dependencies.  This method will do nothing if the format
512     * is already intialized.
513     */
514    final void initializeIfNeeded(Catalog catalog) {
515        if (!initialized) {
516            initialized = true;
517            this.catalog = catalog;
518
519            /* Initialize objects serialized by an older Format class. */
520            if (latestFormat == null) {
521                latestFormat = this;
522            }
523            if (reader == null) {
524                reader = this;
525            }
526
527            /*
528             * The class is only guaranteed to be available in live (not raw)
529             * mode, for the current version of the format.
530             */
531            if (type == null &&
532                isCurrentVersion() &&
533                (isSimple() || !catalog.isRawAccess())) {
534                getExistingType();
535            }
536
537            /* Perform subclass-specific initialization. */
538            initialize
539                (catalog, catalog.getInitVersion(this, false /*forReader*/));
540            reader.initializeReader
541                (catalog, catalog.getInitVersion(this, true /*forReader*/),
542                 this);
543        }
544    }
545
546    /**
547     * Called to initialize a separate Reader implementation.  This method is
548     * called when no separate Reader exists, and does nothing.
549     */
550    public void initializeReader(Catalog catalog,
551                                 int initVersion,
552                                 Format oldFormat) {
553    }
554
555    /**
556     * Adds all interfaces and superclasses to the supertypes set.
557     */
558    private void addSupertypes() {
559        addInterfaces(type);
560        Class stype = type.getSuperclass();
561        while (stype != null && stype != Object.class) {
562            supertypes.add(stype.getName());
563            addInterfaces(stype);
564            stype = stype.getSuperclass();
565        }
566    }
567
568    /**
569     * Recursively adds interfaces to the supertypes set.
570     */
571    private void addInterfaces(Class cls) {
572        Class[] interfaces = cls.getInterfaces();
573        for (Class iface : interfaces) {
574            if (iface != Enhanced.class) {
575                supertypes.add(iface.getName());
576                addInterfaces(iface);
577            }
578        }
579    }
580
581    /**
582     * Certain formats (ProxiedFormat for example) prohibit nested fields that
583     * reference the parent object. [#15815]
584     */
585    boolean areNestedRefsProhibited() {
586        return false;
587    }
588
589    /* -- Start of RawType interface methods. -- */
590
591    public String getClassName() {
592        return className;
593    }
594
595    public int getVersion() {
596        ClassMetadata meta = getClassMetadata();
597        if (meta != null) {
598            return meta.getVersion();
599        } else {
600            return 0;
601        }
602    }
603
604    public Format getSuperType() {
605        return superFormat;
606    }
607
608    /* -- RawType methods that are overridden as needed in subclasses. -- */
609
610    public boolean isSimple() {
611        return false;
612    }
613
614    public boolean isPrimitive() {
615        return false;
616    }
617
618    public boolean isEnum() {
619        return false;
620    }
621
622    public List<String> getEnumConstants() {
623        return null;
624    }
625
626    public boolean isArray() {
627        return false;
628    }
629
630    public int getDimensions() {
631        return 0;
632    }
633
634    public Format getComponentType() {
635        return null;
636    }
637
638    public Map<String,RawField> getFields() {
639        return null;
640    }
641
642    /* -- End of RawType methods. -- */
643
644    /* -- Methods that may optionally be overridden by subclasses. -- */
645
646    /**
647     * Called by EntityOutput in rawAccess mode to determine whether an object
648     * type is allowed to be assigned to a given field type.
649     */
650    boolean isAssignableTo(Format format) {
651        if (proxiedFormat != null) {
652            return proxiedFormat.isAssignableTo(format);
653        } else {
654            return format == this ||
655                   format.id == ID_OBJECT ||
656                   supertypes.contains(format.className);
657        }
658    }
659
660    /**
661     * For primitive types only, returns their associated wrapper type.
662     */
663    Format getWrapperFormat() {
664        return null;
665    }
666
667    /**
668     * Returns whether this format class is an entity class.
669     */
670    boolean isEntity() {
671        return false;
672    }
673
674    /**
675     * Returns whether this class is present in the EntityModel.  Returns false
676     * for a simple type, array type, or enum type.
677     */
678    boolean isModelClass() {
679        return false;
680    }
681
682    /**
683     * Returns the original model class metadata used to create this class, or
684     * null if this is not a model class.
685     */
686    ClassMetadata getClassMetadata() {
687        return null;
688    }
689
690    /**
691     * Returns the original model entity metadata used to create this class, or
692     * null if this is not an entity class.
693     */
694    EntityMetadata getEntityMetadata() {
695        return null;
696    }
697
698    /**
699     * For an entity class or subclass, returns the base entity class; returns
700     * null in other cases.
701     */
702    Format getEntityFormat() {
703        return null;
704    }
705
706    /**
707     * Called for an existing format that may not equal the current format for
708     * the same class.
709     *
710     * <p>If this method returns true, then it must have determined that the
711     * old and new formats are equal, and it must have called either
712     * Evolver.useOldFormat or useEvolvedFormat.  If this method returns false,
713     * then it must have determined that the old format could not be evolved to
714     * the new format, and it must have called Evolver.addInvalidMutation,
715     * addMissingMutation or addEvolveError.</p>
716     */
717    abstract boolean evolve(Format newFormat, Evolver evolver);
718
719    /**
720     * Called when a Converter handles evolution of a class, but we may still
721     * need to evolve the metadata.
722     */
723    boolean evolveMetadata(Format newFormat,
724                           Converter converter,
725                           Evolver evolver) {
726        return true;
727    }
728
729    /**
730     * Returns whether this format is the current format for its class.  If
731     * false is returned, this format is setup to evolve to the current format.
732     */
733    final boolean isCurrentVersion() {
734        return latestFormat == this && !deleted;
735    }
736
737    /**
738     * Returns whether this format has the same class as the given format,
739     * irrespective of version changes and renaming.
740     */
741    final boolean isSameClass(Format other) {
742        return latestFormat == other.latestFormat;
743    }
744
745    /* -- Abstract methods that must be implemented by subclasses. -- */
746
747    /**
748     * Initializes an uninitialized format, initializing its related formats
749     * (superclass formats and array component formats) first.
750     */
751    abstract void initialize(Catalog catalog, int initVersion);
752
753    /**
754     * Calls catalog.createFormat for formats that this format depends on, or
755     * that should also be persistent.
756     */
757    abstract void collectRelatedFormats(Catalog catalog,
758                                        Map<String,Format> newFormats);
759
760    /*
761     * The remaining methods are used to read objects from data bytes via
762     * EntityInput, and to write objects as data bytes via EntityOutput.
763     * Ultimately these methods call methods in the Accessor interface to
764     * get/set fields in the object.  Most methods have a rawAccess parameter
765     * that determines whether the object is a raw object or a real persistent
766     * object.
767     *
768     * The first group of methods are abstract and must be implemented by
769     * format classes.  The second group have default implementations that
770     * throw UnsupportedOperationException and may optionally be overridden.
771     */
772
773    /**
774     * Creates an array of the format's class of the given length, as if
775     * Array.newInstance(getType(), len) were called.  Formats implement this
776     * method for specific classes, or call the accessor, to avoid the
777     * reflection overhead of Array.newInstance.
778     */
779    abstract Object newArray(int len);
780
781    /**
782     * Creates a new instance of the target class using its default
783     * constructor.  Normally this creates an empty object, and readObject() is
784     * called next to fill in the contents.  This is done in two steps to allow
785     * the instance to be registered by EntityInput before reading the
786     * contents.  This allows the fields in an object or a nested object to
787     * refer to the parent object in a graph.
788     *
789     * Alternatively, this method may read all or the first portion of the
790     * data, rather than that being done by readObject().  This is required for
791     * simple types and enums, where the object cannot be created without
792     * reading the data.  In these cases, there is no possibility that the
793     * parent object will be referenced by the child object in the graph.  It
794     * should not be done in other cases, or the graph references may not be
795     * maintained faithfully.
796     *
797     * Is public only in order to implement the Reader interface.  Note that
798     * this method should only be called directly in raw conversion mode or
799     * during conversion of an old format.  Normally it should be called via
800     * the getReader method and the Reader interface.
801     */
802    public abstract Object newInstance(EntityInput input, boolean rawAccess);
803
804    /**
805     * Called after newInstance() to read the rest of the data bytes and fill
806     * in the object contents.  If the object was read completely by
807     * newInstance(), this method does nothing.
808     *
809     * Is public only in order to implement the Reader interface.  Note that
810     * this method should only be called directly in raw conversion mode or
811     * during conversion of an old format.  Normally it should be called via
812     * the getReader method and the Reader interface.
813     */
814    public abstract Object readObject(Object o,
815                                      EntityInput input,
816                                      boolean rawAccess);
817
818    /**
819     * Writes a given instance of the target class to the output data bytes.
820     * This is the complement of the newInstance()/readObject() pair.
821     */
822    abstract void writeObject(Object o, EntityOutput output, boolean rawAccess);
823
824    /**
825     * Skips over the object's contents, as if readObject() were called, but
826     * without returning an object.  Used for extracting secondary key bytes
827     * without having to instantiate the object.  For reference types, the
828     * format ID is read just before calling this method, so this method is
829     * responsible for skipping everything following the format ID.
830     */
831    abstract void skipContents(RecordInput input);
832
833    /* -- More methods that may optionally be overridden by subclasses. -- */
834
835    /**
836     * When extracting a secondary key, called to skip over all fields up to
837     * the given secondary key field.  Returns the format of the key field
838     * found, or null if the field is not present (nullified) in the object.
839     */
840    Format skipToSecKey(RecordInput input, String keyName) {
841        throw new UnsupportedOperationException(toString());
842    }
843
844    /**
845     * Called after skipToSecKey() to copy the data bytes of a singular
846     * (XXX_TO_ONE) key field.
847     */
848    void copySecKey(RecordInput input, RecordOutput output) {
849        throw new UnsupportedOperationException(toString());
850    }
851
852    /**
853     * Called after skipToSecKey() to copy the data bytes of an array or
854     * collection (XXX_TO_MANY) key field.
855     */
856    void copySecMultiKey(RecordInput input, Format keyFormat, Set results) {
857        throw new UnsupportedOperationException(toString());
858    }
859
860    /**
861     * Nullifies the given key field in the given RawObject --  rawAccess mode
862     * is implied.
863     */
864    boolean nullifySecKey(Catalog catalog,
865                          Object entity,
866                          String keyName,
867                          Object keyElement) {
868        throw new UnsupportedOperationException(toString());
869    }
870
871    /**
872     * Returns whether the entity's primary key field is null or zero, as
873     * defined for primary keys that are assigned from a sequence.
874     */
875    boolean isPriKeyNullOrZero(Object o, boolean rawAccess) {
876        throw new UnsupportedOperationException(toString());
877    }
878
879    /**
880     * Gets the primary key field from the given object and writes it to the
881     * given output data bytes.  This is a separate operation because the
882     * primary key data bytes are stored separately from the rest of the
883     * record.
884     */
885    void writePriKey(Object o, EntityOutput output, boolean rawAccess) {
886        throw new UnsupportedOperationException(toString());
887    }
888
889    /**
890     * Reads the primary key from the given input bytes and sets the primary
891     * key field in the given object.  This is complement of writePriKey().
892     *
893     * Is public only in order to implement the Reader interface.  Note that
894     * this method should only be called directly in raw conversion mode or
895     * during conversion of an old format.  Normally it should be called via
896     * the getReader method and the Reader interface.
897     */
898    public void readPriKey(Object o, EntityInput input, boolean rawAccess) {
899        throw new UnsupportedOperationException(toString());
900    }
901
902    /**
903     * Validates and returns the simple integer key format for a sequence key
904     * associated with this format.
905     *
906     * For a composite key type, the format of the one and only field is
907     * returned.  For a simple integer type, this format is returned.
908     * Otherwise (the default implementation), an IllegalArgumentException is
909     * thrown.
910     */
911    Format getSequenceKeyFormat() {
912        throw new IllegalArgumentException
913            ("Type not allowed for sequence: " + getClassName());
914    }
915
916    /**
917     * Converts a RawObject to a current class object and adds the converted
918     * pair to the converted map.
919     */
920    Object convertRawObject(Catalog catalog,
921                            boolean rawAccess,
922                            RawObject rawObject,
923                            IdentityHashMap converted) {
924        throw new UnsupportedOperationException(toString());
925    }
926
927    @Override
928    public String toString() {
929        return "[RawType class: " + getClassName() +
930               " version: " + getVersion() +
931               " internal: " + getClass().getName() +
932               ((reader != null) ?
933                   (" reader: " + reader.getClass().getName()) : "") +
934               ']';
935    }
936}
937