/* 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.ext.*; import com.db4o.internal.*; import com.db4o.internal.activation.*; import com.db4o.marshall.*; import com.db4o.typehandlers.*; /** * Wraps the low-level details of reading a Buffer, which in turn is a glorified byte array. * * @exclude */ public class UnmarshallingContext extends ObjectReferenceContext implements HandlerVersionContext, ReferenceActivationContext { private Object _object; private int _addToIDTree; private boolean _checkIDTree; public UnmarshallingContext(Transaction transaction, ByteArrayBuffer buffer, ObjectReference ref, int addToIDTree, boolean checkIDTree) { super(transaction, buffer, null, ref); _addToIDTree = addToIDTree; _checkIDTree = checkIDTree; } public UnmarshallingContext(Transaction transaction, ObjectReference ref, int addToIDTree, boolean checkIDTree) { this(transaction, null, ref, addToIDTree, checkIDTree); } public Object read(){ if(! beginProcessing()){ return _object; } readBuffer(objectId()); if(buffer() == null){ endProcessing(); return _object; } ClassMetadata classMetadata = readObjectHeader(); if(classMetadata == null){ invalidSlot(); endProcessing(); return _object; } _reference.classMetadata(classMetadata); adjustActivationDepth(); if(_checkIDTree){ Object objectInCacheFromClassCreation = transaction().objectForIdFromCache(objectId()); if(objectInCacheFromClassCreation != null){ _object = objectInCacheFromClassCreation; endProcessing(); return _object; } } if(peekPersisted()){ _object = classMetadata().instantiateTransient(this); }else{ _object = classMetadata().instantiate(this); } endProcessing(); return _object; } private void invalidSlot() { if(container().config().recoveryMode()){ return; } throw new InvalidSlotException("id: " + objectId()); } private void adjustActivationDepth() { if (UnknownActivationDepth.INSTANCE == _activationDepth) { _activationDepth = container().defaultActivationDepth(classMetadata()); } } private ActivationDepthProvider activationDepthProvider() { return container().activationDepthProvider(); } public Object readFullyActivatedObjectForKeys(TypeHandler4 handler) { Object obj = readObject(handler); if(obj == null){ return obj; } ActivationDepth activationDepth = activationDepthProvider().activationDepth(Integer.MAX_VALUE, ActivationMode.ACTIVATE); container().activate(transaction(), obj, activationDepth); return obj; } public Object readFieldValue (FieldMetadata field){ readBuffer(objectId()); if(buffer() == null){ return null; } ClassMetadata classMetadata = readObjectHeader(); if(classMetadata == null){ return null; } return readFieldValue(classMetadata, field); } private Object readFieldValue(ClassMetadata classMetadata, FieldMetadata field) { if(! classMetadata.seekToField(this, field)){ return null; } return field.read(this); } private ClassMetadata readObjectHeader() { _objectHeader = new ObjectHeader(container(), byteArrayBuffer()); ClassMetadata classMetadata = _objectHeader.classMetadata(); if(classMetadata == null){ return null; } return classMetadata; } private void readBuffer(int id) { if (buffer() == null && id > 0) { buffer(container().readBufferById(transaction(), id)); } } private boolean beginProcessing() { return _reference.beginProcessing(); } private void endProcessing() { _reference.endProcessing(); } public void setStateClean() { _reference.setStateClean(); } public Object persistentObject() { return _object; } public void setObjectWeak(Object obj) { _reference.setObjectWeak(container(), obj); } protected boolean peekPersisted() { return _addToIDTree == Const4.TRANSIENT; } public Config4Class classConfig() { return classMetadata().config(); } public void persistentObject(Object obj) { _object = obj; } }