001: /*-
002: * See the file LICENSE for redistribution information.
003: *
004: * Copyright (c) 2002,2008 Oracle. All rights reserved.
005: *
006: * $Id: Format.java,v 1.29.2.8 2008/01/07 15:14:19 cwl Exp $
007: */
008:
009: package com.sleepycat.persist.impl;
010:
011: import java.io.Serializable;
012: import java.util.HashSet;
013: import java.util.IdentityHashMap;
014: import java.util.List;
015: import java.util.Map;
016: import java.util.Set;
017:
018: import com.sleepycat.persist.evolve.Converter;
019: import com.sleepycat.persist.model.ClassMetadata;
020: import com.sleepycat.persist.model.EntityMetadata;
021: import com.sleepycat.persist.raw.RawField;
022: import com.sleepycat.persist.raw.RawObject;
023: import com.sleepycat.persist.raw.RawType;
024:
025: /**
026: * The base class for all object formats. Formats are used to define the
027: * stored layout for all persistent classes, including simple types.
028: *
029: * The design documentation below describes the storage format for entities and
030: * its relationship to information stored per format in the catalog.
031: *
032: * Requirements
033: * ------------
034: * + Provides EntityBinding for objects and EntryBinding for keys.
035: * + Provides SecondaryKeyCreator, SecondaryMultiKeyCreator and
036: * SecondaryMultiKeyNullifier (SecondaryKeyNullifier is redundant).
037: * + Works with reflection and bytecode enhancement.
038: * + For reflection only, works with any entity model not just annotations.
039: * + Bindings are usable independently of the persist API.
040: * + Performance is almost equivalent to hand coded tuple bindings.
041: * + Small performance penalty for compatible class changes (new fields,
042: * widening).
043: * + Secondary key create/nullify do not have to deserialize the entire record;
044: * in other words, store secondary keys at the start of the data.
045: *
046: * Class Format
047: * ------------
048: * Every distinct class format is given a unique format ID. Class IDs are not
049: * equivalent to class version numbers (as in the version property of @Entity
050: * and @Persistent) because the format can change when the version number does
051: * not. Changes that cause a unique format ID to be assigned are:
052: *
053: * + Add field.
054: * + Widen field type.
055: * + Change primitive type to primitive wrapper class.
056: * + Add or drop secondary key.
057: * + Any incompatible class change.
058: *
059: * The last item, incompatible class changes, also correspond to a class
060: * version change.
061: *
062: * For each distinct class format the following information is conceptually
063: * stored in the catalog, keyed by format ID.
064: *
065: * - Class name
066: * - Class version number
067: * - Superclass format
068: * - Kind: simple, enum, complex, array
069: * - For kind == simple:
070: * - Primitive class
071: * - For kind == enum:
072: * - Array of constant names, sorted by name.
073: * - For kind == complex:
074: * - Primary key fieldInfo, or null if no primary key is declared
075: * - Array of secondary key fieldInfo, sorted by field name
076: * - Array of other fieldInfo, sorted by field name
077: * - For kind == array:
078: * - Component class format
079: * - Number of array dimensions
080: * - Other metadata for RawType
081: *
082: * Where fieldInfo is:
083: * - Field name
084: * - Field class
085: * - Other metadata for RawField
086: *
087: * Data Layout
088: * -----------
089: * For each entity instance the data layout is as follows:
090: *
091: * instanceData: formatId keyFields... nonKeyFields...
092: * keyFields: fieldValue...
093: * nonKeyFields: fieldValue...
094: *
095: * The formatId is the (positive non-zero) ID of a class format, defined above.
096: * This is ID of the most derived class of the instance. It is stored as a
097: * packed integer.
098: *
099: * 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 {
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 super Format;
294: private Format latestFormat;
295: private Format previousFormat;
296: private Set<String> super types;
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: super types = 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 super Format;
407: }
408:
409: /**
410: * Called to set the format of the superclass during initialize().
411: */
412: final void setSuperFormat(Format super Format) {
413: this .super Format = super Format;
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 && isCurrentVersion()
532: && (isSimple() || !catalog.isRawAccess())) {
533: getExistingType();
534: }
535:
536: /* Perform subclass-specific initialization. */
537: initialize(catalog, catalog
538: .getInitVersion(this , false /*forReader*/));
539: reader.initializeReader(catalog, catalog.getInitVersion(
540: this , true /*forReader*/), this );
541: }
542: }
543:
544: /**
545: * Called to initialize a separate Reader implementation. This method is
546: * called when no separate Reader exists, and does nothing.
547: */
548: public void initializeReader(Catalog catalog, int initVersion,
549: Format oldFormat) {
550: }
551:
552: /**
553: * Adds all interfaces and superclasses to the supertypes set.
554: */
555: private void addSupertypes() {
556: addInterfaces(type);
557: Class stype = type.getSuperclass();
558: while (stype != null && stype != Object.class) {
559: super types.add(stype.getName());
560: addInterfaces(stype);
561: stype = stype.getSuperclass();
562: }
563: }
564:
565: /**
566: * Recursively adds interfaces to the supertypes set.
567: */
568: private void addInterfaces(Class cls) {
569: Class[] interfaces = cls.getInterfaces();
570: for (Class iface : interfaces) {
571: if (iface != Enhanced.class) {
572: super types.add(iface.getName());
573: addInterfaces(iface);
574: }
575: }
576: }
577:
578: /**
579: * Certain formats (ProxiedFormat for example) prohibit nested fields that
580: * reference the parent object. [#15815]
581: */
582: boolean areNestedRefsProhibited() {
583: return false;
584: }
585:
586: /* -- Start of RawType interface methods. -- */
587:
588: public String getClassName() {
589: return className;
590: }
591:
592: public int getVersion() {
593: ClassMetadata meta = getClassMetadata();
594: if (meta != null) {
595: return meta.getVersion();
596: } else {
597: return 0;
598: }
599: }
600:
601: public Format getSuperType() {
602: return super Format;
603: }
604:
605: /* -- RawType methods that are overridden as needed in subclasses. -- */
606:
607: public boolean isSimple() {
608: return false;
609: }
610:
611: public boolean isPrimitive() {
612: return false;
613: }
614:
615: public boolean isEnum() {
616: return false;
617: }
618:
619: public List<String> getEnumConstants() {
620: return null;
621: }
622:
623: public boolean isArray() {
624: return false;
625: }
626:
627: public int getDimensions() {
628: return 0;
629: }
630:
631: public Format getComponentType() {
632: return null;
633: }
634:
635: public Map<String, RawField> getFields() {
636: return null;
637: }
638:
639: /* -- End of RawType methods. -- */
640:
641: /* -- Methods that may optionally be overridden by subclasses. -- */
642:
643: /**
644: * Called by EntityOutput in rawAccess mode to determine whether an object
645: * type is allowed to be assigned to a given field type.
646: */
647: boolean isAssignableTo(Format format) {
648: if (proxiedFormat != null) {
649: return proxiedFormat.isAssignableTo(format);
650: } else {
651: return format == this || format.id == ID_OBJECT
652: || super types.contains(format.className);
653: }
654: }
655:
656: /**
657: * For primitive types only, returns their associated wrapper type.
658: */
659: Format getWrapperFormat() {
660: return null;
661: }
662:
663: /**
664: * Returns whether this format class is an entity class.
665: */
666: boolean isEntity() {
667: return false;
668: }
669:
670: /**
671: * Returns whether this class is present in the EntityModel. Returns false
672: * for a simple type, array type, or enum type.
673: */
674: boolean isModelClass() {
675: return false;
676: }
677:
678: /**
679: * Returns the original model class metadata used to create this class, or
680: * null if this is not a model class.
681: */
682: ClassMetadata getClassMetadata() {
683: return null;
684: }
685:
686: /**
687: * Returns the original model entity metadata used to create this class, or
688: * null if this is not an entity class.
689: */
690: EntityMetadata getEntityMetadata() {
691: return null;
692: }
693:
694: /**
695: * For an entity class or subclass, returns the base entity class; returns
696: * null in other cases.
697: */
698: Format getEntityFormat() {
699: return null;
700: }
701:
702: /**
703: * Called for an existing format that may not equal the current format for
704: * the same class.
705: *
706: * <p>If this method returns true, then it must have determined that the
707: * old and new formats are equal, and it must have called either
708: * Evolver.useOldFormat or useEvolvedFormat. If this method returns false,
709: * then it must have determined that the old format could not be evolved to
710: * the new format, and it must have called Evolver.addInvalidMutation,
711: * addMissingMutation or addEvolveError.</p>
712: */
713: abstract boolean evolve(Format newFormat, Evolver evolver);
714:
715: /**
716: * Called when a Converter handles evolution of a class, but we may still
717: * need to evolve the metadata.
718: */
719: boolean evolveMetadata(Format newFormat, Converter converter,
720: Evolver evolver) {
721: return true;
722: }
723:
724: /**
725: * Returns whether this format is the current format for its class. If
726: * false is returned, this format is setup to evolve to the current format.
727: */
728: final boolean isCurrentVersion() {
729: return latestFormat == this && !deleted;
730: }
731:
732: /**
733: * Returns whether this format has the same class as the given format,
734: * irrespective of version changes and renaming.
735: */
736: final boolean isSameClass(Format other) {
737: return latestFormat == other.latestFormat;
738: }
739:
740: /* -- Abstract methods that must be implemented by subclasses. -- */
741:
742: /**
743: * Initializes an uninitialized format, initializing its related formats
744: * (superclass formats and array component formats) first.
745: */
746: abstract void initialize(Catalog catalog, int initVersion);
747:
748: /**
749: * Calls catalog.createFormat for formats that this format depends on, or
750: * that should also be persistent.
751: */
752: abstract void collectRelatedFormats(Catalog catalog,
753: Map<String, Format> newFormats);
754:
755: /*
756: * The remaining methods are used to read objects from data bytes via
757: * EntityInput, and to write objects as data bytes via EntityOutput.
758: * Ultimately these methods call methods in the Accessor interface to
759: * get/set fields in the object. Most methods have a rawAccess parameter
760: * that determines whether the object is a raw object or a real persistent
761: * object.
762: *
763: * The first group of methods are abstract and must be implemented by
764: * format classes. The second group have default implementations that
765: * throw UnsupportedOperationException and may optionally be overridden.
766: */
767:
768: /**
769: * Creates an array of the format's class of the given length, as if
770: * Array.newInstance(getType(), len) were called. Formats implement this
771: * method for specific classes, or call the accessor, to avoid the
772: * reflection overhead of Array.newInstance.
773: */
774: abstract Object newArray(int len);
775:
776: /**
777: * Creates a new instance of the target class using its default
778: * constructor. Normally this creates an empty object, and readObject() is
779: * called next to fill in the contents. This is done in two steps to allow
780: * the instance to be registered by EntityInput before reading the
781: * contents. This allows the fields in an object or a nested object to
782: * refer to the parent object in a graph.
783: *
784: * Alternatively, this method may read all or the first portion of the
785: * data, rather than that being done by readObject(). This is required for
786: * simple types and enums, where the object cannot be created without
787: * reading the data. In these cases, there is no possibility that the
788: * parent object will be referenced by the child object in the graph. It
789: * should not be done in other cases, or the graph references may not be
790: * maintained faithfully.
791: *
792: * Is public only in order to implement the Reader interface. Note that
793: * this method should only be called directly in raw conversion mode or
794: * during conversion of an old format. Normally it should be called via
795: * the getReader method and the Reader interface.
796: */
797: public abstract Object newInstance(EntityInput input,
798: boolean rawAccess);
799:
800: /**
801: * Called after newInstance() to read the rest of the data bytes and fill
802: * in the object contents. If the object was read completely by
803: * newInstance(), this method does nothing.
804: *
805: * Is public only in order to implement the Reader interface. Note that
806: * this method should only be called directly in raw conversion mode or
807: * during conversion of an old format. Normally it should be called via
808: * the getReader method and the Reader interface.
809: */
810: public abstract Object readObject(Object o, EntityInput input,
811: boolean rawAccess);
812:
813: /**
814: * Writes a given instance of the target class to the output data bytes.
815: * This is the complement of the newInstance()/readObject() pair.
816: */
817: abstract void writeObject(Object o, EntityOutput output,
818: boolean rawAccess);
819:
820: /**
821: * Skips over the object's contents, as if readObject() were called, but
822: * without returning an object. Used for extracting secondary key bytes
823: * without having to instantiate the object. For reference types, the
824: * format ID is read just before calling this method, so this method is
825: * responsible for skipping everything following the format ID.
826: */
827: abstract void skipContents(RecordInput input);
828:
829: /* -- More methods that may optionally be overridden by subclasses. -- */
830:
831: /**
832: * When extracting a secondary key, called to skip over all fields up to
833: * the given secondary key field. Returns the format of the key field
834: * found, or null if the field is not present (nullified) in the object.
835: */
836: Format skipToSecKey(RecordInput input, String keyName) {
837: throw new UnsupportedOperationException(toString());
838: }
839:
840: /**
841: * Called after skipToSecKey() to copy the data bytes of a singular
842: * (XXX_TO_ONE) key field.
843: */
844: void copySecKey(RecordInput input, RecordOutput output) {
845: throw new UnsupportedOperationException(toString());
846: }
847:
848: /**
849: * Called after skipToSecKey() to copy the data bytes of an array or
850: * collection (XXX_TO_MANY) key field.
851: */
852: void copySecMultiKey(RecordInput input, Format keyFormat,
853: Set results) {
854: throw new UnsupportedOperationException(toString());
855: }
856:
857: /**
858: * Nullifies the given key field in the given RawObject -- rawAccess mode
859: * is implied.
860: */
861: boolean nullifySecKey(Catalog catalog, Object entity,
862: String keyName, Object keyElement) {
863: throw new UnsupportedOperationException(toString());
864: }
865:
866: /**
867: * Returns whether the entity's primary key field is null or zero, as
868: * defined for primary keys that are assigned from a sequence.
869: */
870: boolean isPriKeyNullOrZero(Object o, boolean rawAccess) {
871: throw new UnsupportedOperationException(toString());
872: }
873:
874: /**
875: * Gets the primary key field from the given object and writes it to the
876: * given output data bytes. This is a separate operation because the
877: * primary key data bytes are stored separately from the rest of the
878: * record.
879: */
880: void writePriKey(Object o, EntityOutput output, boolean rawAccess) {
881: throw new UnsupportedOperationException(toString());
882: }
883:
884: /**
885: * Reads the primary key from the given input bytes and sets the primary
886: * key field in the given object. This is complement of writePriKey().
887: *
888: * Is public only in order to implement the Reader interface. Note that
889: * this method should only be called directly in raw conversion mode or
890: * during conversion of an old format. Normally it should be called via
891: * the getReader method and the Reader interface.
892: */
893: public void readPriKey(Object o, EntityInput input,
894: boolean rawAccess) {
895: throw new UnsupportedOperationException(toString());
896: }
897:
898: /**
899: * Validates and returns the simple integer key format for a sequence key
900: * associated with this format.
901: *
902: * For a composite key type, the format of the one and only field is
903: * returned. For a simple integer type, this format is returned.
904: * Otherwise (the default implementation), an IllegalArgumentException is
905: * thrown.
906: */
907: Format getSequenceKeyFormat() {
908: throw new IllegalArgumentException(
909: "Type not allowed for sequence: " + getClassName());
910: }
911:
912: /**
913: * Converts a RawObject to a current class object and adds the converted
914: * pair to the converted map.
915: */
916: Object convertRawObject(Catalog catalog, boolean rawAccess,
917: RawObject rawObject, IdentityHashMap converted) {
918: throw new UnsupportedOperationException(toString());
919: }
920:
921: @Override
922: public String toString() {
923: return "[RawType class: "
924: + getClassName()
925: + " version: "
926: + getVersion()
927: + " internal: "
928: + getClass().getName()
929: + ((reader != null) ? (" reader: " + reader.getClass()
930: .getName()) : "") + ']';
931: }
932: }
|