/* This file is part of the db4o object database http://www.db4o.com
Copyright (C) 2004 - 2011 Versant Corporation http://www.versant.com
db4o is free software; you can redistribute it and/or modify it under
the terms of version 3 of the GNU General Public License as published
by the Free Software Foundation.
db4o is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with this program. If not, see http://www.gnu.org/licenses/. */
package com.db4o.internal.handlers.versions;
import com.db4o.internal.*;
import com.db4o.internal.activation.*;
import com.db4o.internal.marshall.*;
import com.db4o.internal.slots.*;
import com.db4o.marshall.*;
import com.db4o.typehandlers.*;
public class OpenTypeHandler7 extends OpenTypeHandler {
public OpenTypeHandler7(ObjectContainerBase container) {
super(container);
}
public Object read(ReadContext readContext) {
InternalReadContext context = (InternalReadContext) readContext;
int payloadOffset = context.readInt();
if (payloadOffset == 0) {
context.notifyNullReferenceSkipped();
return null;
}
int savedOffSet = context.offset();
try {
TypeHandler4 typeHandler = readTypeHandler(context, payloadOffset);
if (typeHandler == null) {
return null;
}
if (isPlainObject(typeHandler)) {
return readPlainObject(readContext);
}
seekSecondaryOffset(context, typeHandler);
return context.readAtCurrentSeekPosition(typeHandler);
} finally {
context.seek(savedOffSet);
}
}
@Override
public void defragment(DefragmentContext context) {
int payLoadOffSet = context.readInt();
if (payLoadOffSet == 0) {
return;
}
int savedOffSet = context.offset();
context.seek(payLoadOffSet);
int classMetadataId = context.copyIDReturnOriginalID();
TypeHandler4 typeHandler = correctTypeHandlerVersionFor(context, classMetadataId);
if (typeHandler != null) {
if (isPlainObject(typeHandler)) {
context.copySlotlessID();
} else {
seekSecondaryOffset(context, typeHandler);
context.defragment(typeHandler);
}
}
context.seek(savedOffSet);
}
private Object readPlainObject(ReadContext context) {
int id = context.readInt();
Transaction transaction = context.transaction();
Object obj = transaction.objectForIdFromCache(id);
if (obj != null) {
return obj;
}
obj = new Object();
addReference(context, obj, id);
return obj;
}
private void addReference(Context context, Object obj, int id) {
final Transaction transaction = context.transaction();
final ObjectReference ref = new ObjectReference(id) {
boolean _firstUpdate = true;
@Override
public void writeUpdate(Transaction transaction, UpdateDepth updatedepth) {
if (!_firstUpdate) {
super.writeUpdate(transaction, updatedepth);
return;
}
_firstUpdate = false;
ObjectContainerBase container = transaction.container();
setStateClean();
MarshallingContext context = new MarshallingContext(transaction, this, updatedepth, false);
Handlers4.write(classMetadata().typeHandler(), context, getObject());
int length = container().blockConverter().blockAlignedBytes(context.marshalledLength());
Slot slot = context.allocateNewSlot(length);
Pointer4 pointer = new Pointer4(getID(), slot);
ByteArrayBuffer buffer = context.toWriteBuffer(pointer);
container.writeUpdate(transaction, pointer, classMetadata(), ArrayType.NONE, buffer);
if (isActive()) {
setStateClean();
}
}
};
ref.classMetadata(transaction.container().classMetadataForID(Handlers4.UNTYPED_ID));
ref.setObjectWeak(transaction.container(), obj);
transaction.addNewReference(ref);
}
}