/* 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.marshall; import com.db4o.foundation.*; import com.db4o.internal.*; import com.db4o.internal.activation.*; import com.db4o.marshall.*; import com.db4o.typehandlers.*; /** * @exclude */ public abstract class AbstractReadContext extends AbstractBufferContext implements InternalReadContext { protected ActivationDepth _activationDepth = UnknownActivationDepth.INSTANCE; private boolean _lastReferenceReadWasReallyNull = false; protected AbstractReadContext(Transaction transaction, ReadBuffer buffer){ super(transaction, buffer); } protected AbstractReadContext(Transaction transaction){ this(transaction, null); } public final Object read(TypeHandler4 handlerType) { return readObject(handlerType); } public final Object readObject(TypeHandler4 handlerType) { if (null == handlerType) { throw new ArgumentNullException(); } final TypeHandler4 handler = HandlerRegistry.correctHandlerVersion(this, handlerType); return slotFormat().doWithSlotIndirection(this, handler, new Closure4() { public Object run() { return readAtCurrentSeekPosition(handler); } }); } public Object readAtCurrentSeekPosition(TypeHandler4 handler){ if(Handlers4.useDedicatedSlot(this, handler)){ return readObject(); } return Handlers4.readValueType(this, handler); } public final Object readObject() { int objectId = readInt(); if (objectId == 0) { _lastReferenceReadWasReallyNull = true; return null; } _lastReferenceReadWasReallyNull = false; if(objectId == Const4.INVALID_OBJECT_ID) { return null; } final ClassMetadata classMetadata = classMetadataForObjectId(objectId); if (null == classMetadata) { // TODO: throw here return null; } ActivationDepth depth = activationDepth().descend(classMetadata); if (peekPersisted()) { return container().peekPersisted(transaction(), objectId, depth, false); } Object obj = container().getByID2(transaction(), objectId); if (null == obj) { return null; } // this is OK for boxed value types. They will not be added // to the list, since they will not be found in the ID tree. container().stillToActivate(container().activationContextFor(transaction(), obj, depth)); return obj; } private ClassMetadata classMetadataForObjectId(int objectId) { // TODO: This method is *very* costly as is, since it reads // the whole slot once and doesn't reuse it. Optimize. HardObjectReference hardRef = container().getHardObjectReferenceById(transaction(), objectId); if (null == hardRef || hardRef._reference == null) { // com.db4o.db4ounit.common.querying.CascadeDeleteDeleted return null; } return hardRef._reference.classMetadata(); } protected boolean peekPersisted() { return false; } public ActivationDepth activationDepth() { return _activationDepth; } public void activationDepth(ActivationDepth depth){ _activationDepth = depth; } public ReadWriteBuffer readIndirectedBuffer() { int address = readInt(); int length = readInt(); if(address == 0){ return null; } return container().decryptedBufferByAddress(address, length); } public boolean lastReferenceReadWasReallyNull() { return _lastReferenceReadWasReallyNull; } public void notifyNullReferenceSkipped() { _lastReferenceReadWasReallyNull = true; } }