~ubuntu-branches/ubuntu/saucy/db/saucy-proposed

« back to all changes in this revision

Viewing changes to java/src/com/sleepycat/persist/impl/Format.java

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson
  • Date: 2010-11-05 15:02:09 UTC
  • mfrom: (13.1.12 sid)
  • Revision ID: james.westby@ubuntu.com-20101105150209-ppvyn0619pu014xo
Tags: 5.1.19-1ubuntu1
* Resynchronise with Debian.  Remaining changes:
  - Pass --build/--host to configure to support cross-building, and don't
    override CC.
  - Disable the Java build when cross-building, for now.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*-
2
 
 * See the file LICENSE for redistribution information.
3
 
 *
4
 
 * Copyright (c) 2002, 2010 Oracle and/or its affiliates.  All rights reserved.
5
 
 *
6
 
 * $Id$
7
 
 */
8
 
 
9
 
package com.sleepycat.persist.impl;
10
 
 
11
 
import java.io.Serializable;
12
 
import java.util.HashSet;
13
 
import java.util.IdentityHashMap;
14
 
import java.util.List;
15
 
import java.util.Map;
16
 
import java.util.Set;
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.model.EntityModel;
22
 
import com.sleepycat.persist.model.FieldMetadata;
23
 
import com.sleepycat.persist.model.PrimaryKeyMetadata;
24
 
import com.sleepycat.persist.model.SecondaryKeyMetadata;
25
 
import com.sleepycat.persist.raw.RawField;
26
 
import com.sleepycat.persist.raw.RawObject;
27
 
import 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
 
 */
240
 
public 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
 
}