001: /* Copyright (C) 2004 - 2007 db4objects Inc. http://www.db4o.com
002:
003: This file is part of the db4o open source object database.
004:
005: db4o is free software; you can redistribute it and/or modify it under
006: the terms of version 2 of the GNU General Public License as published
007: by the Free Software Foundation and as clarified by db4objects' GPL
008: interpretation policy, available at
009: http://www.db4o.com/about/company/legalpolicies/gplinterpretation/
010: Alternatively you can write to db4objects, Inc., 1900 S Norfolk Street,
011: Suite 350, San Mateo, CA 94403, USA.
012:
013: db4o is distributed in the hope that it will be useful, but WITHOUT ANY
014: WARRANTY; without even the implied warranty of MERCHANTABILITY or
015: FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
016: for more details.
017:
018: You should have received a copy of the GNU General Public License along
019: with this program; if not, write to the Free Software Foundation, Inc.,
020: 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
021: package com.db4o.internal.marshall;
022:
023: import com.db4o.*;
024: import com.db4o.internal.*;
025: import com.db4o.internal.slots.*;
026:
027: public abstract class ObjectMarshaller {
028:
029: public MarshallerFamily _family;
030:
031: protected abstract static class TraverseFieldCommand {
032: private boolean _cancelled = false;
033:
034: public int fieldCount(ClassMetadata classMetadata, Buffer reader) {
035: return classMetadata.readFieldCount(reader);
036: }
037:
038: public boolean cancelled() {
039: return _cancelled;
040: }
041:
042: protected void cancel() {
043: _cancelled = true;
044: }
045:
046: public abstract void processField(FieldMetadata field,
047: boolean isNull, ClassMetadata containingClass);
048: }
049:
050: protected final void traverseFields(MarshallingInfo context,
051: TraverseFieldCommand command) {
052: traverseFields(context.classMetadata(), context.buffer(),
053: context, command);
054: }
055:
056: protected final void traverseFields(ClassMetadata classMetadata,
057: Buffer buffer, FieldListInfo fieldList,
058: TraverseFieldCommand command) {
059: int fieldIndex = 0;
060: while (classMetadata != null && !command.cancelled()) {
061: int fieldCount = command.fieldCount(classMetadata, buffer);
062: for (int i = 0; i < fieldCount && !command.cancelled(); i++) {
063: command.processField(classMetadata.i_fields[i], isNull(
064: fieldList, fieldIndex), classMetadata);
065: fieldIndex++;
066: }
067: classMetadata = classMetadata.i_ancestor;
068: }
069: }
070:
071: protected abstract boolean isNull(FieldListInfo fieldList,
072: int fieldIndex);
073:
074: public abstract void addFieldIndices(ClassMetadata yc,
075: ObjectHeaderAttributes attributes, StatefulBuffer writer,
076: Slot oldSlot);
077:
078: public abstract TreeInt collectFieldIDs(TreeInt tree,
079: ClassMetadata yc, ObjectHeaderAttributes attributes,
080: StatefulBuffer reader, String name);
081:
082: protected StatefulBuffer createWriterForNew(Transaction trans,
083: ObjectReference yo, int updateDepth, int length) {
084:
085: int id = yo.getID();
086: Slot slot = new Slot(-1, length);
087:
088: if (trans instanceof LocalTransaction) {
089: slot = ((LocalTransaction) trans).file().getSlot(length);
090: trans.slotFreeOnRollback(id, slot);
091: }
092: trans.setPointer(id, slot);
093: return createWriterForUpdate(trans, updateDepth, id, slot
094: .address(), slot.length());
095: }
096:
097: protected StatefulBuffer createWriterForUpdate(Transaction a_trans,
098: int updateDepth, int id, int address, int length) {
099:
100: length = a_trans.container().blockAlignedBytes(length);
101: StatefulBuffer writer = new StatefulBuffer(a_trans, length);
102: writer.useSlot(id, address, length);
103: if (Deploy.debug) {
104: writer.writeBegin(Const4.YAPOBJECT);
105: }
106: writer.setUpdateDepth(updateDepth);
107: return writer;
108: }
109:
110: public abstract void deleteMembers(ClassMetadata yc,
111: ObjectHeaderAttributes attributes, StatefulBuffer writer,
112: int a_type, boolean isUpdate);
113:
114: public abstract boolean findOffset(ClassMetadata classMetadata,
115: FieldListInfo fieldListInfo, Buffer buffer,
116: FieldMetadata field);
117:
118: public final void marshallUpdateWrite(Transaction trans,
119: Pointer4 pointer, ObjectReference ref, Object obj,
120: Buffer buffer) {
121:
122: ClassMetadata classMetadata = ref.classMetadata();
123:
124: ObjectContainerBase container = trans.container();
125: container.writeUpdate(trans, pointer, classMetadata, buffer);
126: if (ref.isActive()) {
127: ref.setStateClean();
128: }
129: ref.endProcessing();
130: objectOnUpdate(trans, classMetadata, obj);
131: }
132:
133: private void objectOnUpdate(Transaction transaction,
134: ClassMetadata yc, Object obj) {
135: ObjectContainerBase container = transaction.container();
136: container.callbacks().objectOnUpdate(transaction, obj);
137: yc.dispatchEvent(container, obj, EventDispatcher.UPDATE);
138: }
139:
140: public abstract Object readIndexEntry(ClassMetadata yc,
141: ObjectHeaderAttributes attributes, FieldMetadata yf,
142: StatefulBuffer reader);
143:
144: public abstract ObjectHeaderAttributes readHeaderAttributes(
145: Buffer reader);
146:
147: public abstract void readVirtualAttributes(Transaction trans,
148: ClassMetadata yc, ObjectReference yo,
149: ObjectHeaderAttributes attributes, Buffer reader);
150:
151: public abstract void defragFields(ClassMetadata yapClass,
152: ObjectHeader header, BufferPair readers);
153:
154: public abstract void writeObjectClassID(Buffer reader, int id);
155:
156: public abstract void skipMarshallerInfo(Buffer reader);
157:
158: public final void instantiateFields(
159: final UnmarshallingContext context) {
160: TraverseFieldCommand command = new TraverseFieldCommand() {
161: public void processField(FieldMetadata field,
162: boolean isNull, ClassMetadata containingClass) {
163: if (isNull) {
164: field.set(context.persistentObject(), null);
165: return;
166: }
167: boolean ok = false;
168: try {
169: field.instantiate(context);
170: ok = true;
171: } finally {
172: if (!ok) {
173: cancel();
174: }
175: }
176: }
177: };
178: traverseFields(context, command);
179: }
180:
181: public void marshall(final Object obj,
182: final MarshallingContext context) {
183: final Transaction trans = context.transaction();
184: TraverseFieldCommand command = new TraverseFieldCommand() {
185: private int fieldIndex = -1;
186:
187: public int fieldCount(ClassMetadata classMetadata,
188: Buffer buffer) {
189: int fieldCount = classMetadata.i_fields.length;
190: context.fieldCount(fieldCount);
191: return fieldCount;
192: }
193:
194: public void processField(FieldMetadata field,
195: boolean isNull, ClassMetadata containingClass) {
196: context.nextField();
197: fieldIndex++;
198: Object child = field.getOrCreate(trans, obj);
199: if (child == null) {
200: context.isNull(fieldIndex, true);
201: field
202: .addIndexEntry(trans, context.objectID(),
203: null);
204: return;
205: }
206:
207: if (child instanceof Db4oTypeImpl) {
208: child = ((Db4oTypeImpl) child).storedTo(trans);
209: }
210: field.marshall(context, child);
211: }
212: };
213: traverseFields(context, command);
214: }
215:
216: }
|