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.internal.*;
024:
025: /**
026: * @exclude
027: */
028: public class UnmarshallingContext extends AbstractReadContext implements
029: FieldListInfo, MarshallingInfo {
030:
031: private final ObjectReference _reference;
032:
033: private Object _object;
034:
035: private ObjectHeader _objectHeader;
036:
037: private int _addToIDTree;
038:
039: private boolean _checkIDTree;
040:
041: public UnmarshallingContext(Transaction transaction, Buffer buffer,
042: ObjectReference ref, int addToIDTree, boolean checkIDTree) {
043: super (transaction, buffer);
044: _reference = ref;
045: _addToIDTree = addToIDTree;
046: _checkIDTree = checkIDTree;
047: }
048:
049: public UnmarshallingContext(Transaction transaction,
050: ObjectReference ref, int addToIDTree, boolean checkIDTree) {
051: this (transaction, null, ref, addToIDTree, checkIDTree);
052: }
053:
054: public StatefulBuffer statefulBuffer() {
055: StatefulBuffer buffer = new StatefulBuffer(_transaction,
056: _buffer.length());
057: buffer.setID(objectID());
058: buffer.setInstantiationDepth(activationDepth());
059: _buffer.copyTo(buffer, 0, 0, _buffer.length());
060: buffer.offset(_buffer.offset());
061: return buffer;
062: }
063:
064: public int objectID() {
065: return _reference.getID();
066: }
067:
068: public Object read() {
069: return readInternal(false);
070: }
071:
072: public Object readPrefetch() {
073: return readInternal(true);
074: }
075:
076: private final Object readInternal(
077: boolean doAdjustActivationDepthForPrefetch) {
078: if (!beginProcessing()) {
079: return _object;
080: }
081:
082: readBuffer(objectID());
083:
084: if (_buffer == null) {
085: endProcessing();
086: return _object;
087: }
088:
089: ClassMetadata classMetadata = readObjectHeader();
090:
091: if (classMetadata == null) {
092: endProcessing();
093: return _object;
094: }
095:
096: _reference.classMetadata(classMetadata);
097:
098: if (doAdjustActivationDepthForPrefetch) {
099: adjustActivationDepthForPrefetch();
100: }
101:
102: if (_checkIDTree) {
103: Object objectInCacheFromClassCreation = _transaction
104: .objectForIdFromCache(objectID());
105: if (objectInCacheFromClassCreation != null) {
106: _object = objectInCacheFromClassCreation;
107: endProcessing();
108: return _object;
109: }
110: }
111:
112: if (peekPersisted()) {
113: _object = classMetadata().instantiateTransient(this );
114: } else {
115: _object = classMetadata().instantiate(this );
116: }
117:
118: endProcessing();
119: return _object;
120: }
121:
122: private void adjustActivationDepthForPrefetch() {
123: // We use an instantiationdepth of 1 only, if there is no special
124: // configuration for the class. This is a quick fix due to a problem
125: // instantiating Hashtables. There may be a better workaround that
126: // works with configured objects only to make them fast also.
127: //
128: // An instantiation depth of 1 makes use of possibly prefetched strings
129: // that are carried around in a_bytes.
130: //
131: // TODO: optimize
132:
133: int depth = classMetadata().configOrAncestorConfig() == null ? 1
134: : 0;
135: activationDepth(depth);
136: }
137:
138: public Object readFieldValue(FieldMetadata field) {
139: readBuffer(objectID());
140: if (_buffer == null) {
141: return null;
142: }
143: ClassMetadata classMetadata = readObjectHeader();
144: if (classMetadata == null) {
145: return null;
146: }
147: if (!_objectHeader.objectMarshaller().findOffset(classMetadata,
148: _objectHeader._headerAttributes, _buffer, field)) {
149: return null;
150: }
151: return field.read(this );
152: }
153:
154: private ClassMetadata readObjectHeader() {
155: _objectHeader = new ObjectHeader(container(), _buffer);
156: ClassMetadata classMetadata = _objectHeader.classMetadata();
157: if (classMetadata == null) {
158: return null;
159: }
160: return classMetadata;
161: }
162:
163: private void readBuffer(int id) {
164: if (_buffer == null && id > 0) {
165: _buffer = container().readReaderByID(_transaction, id);
166: }
167: }
168:
169: public ClassMetadata classMetadata() {
170: return _reference.classMetadata();
171: }
172:
173: private boolean beginProcessing() {
174: return _reference.beginProcessing();
175: }
176:
177: private void endProcessing() {
178: _reference.endProcessing();
179: }
180:
181: public void setStateClean() {
182: _reference.setStateClean();
183: }
184:
185: public Object persistentObject() {
186: return _object;
187: }
188:
189: public void setObjectWeak(Object obj) {
190: _reference.setObjectWeak(container(), obj);
191: }
192:
193: public Object readObject() {
194: int id = readInt();
195: int depth = _activationDepth - 1;
196:
197: if (peekPersisted()) {
198: return container().peekPersisted(transaction(), id, depth,
199: false);
200: }
201:
202: Object obj = container().getByID2(transaction(), id);
203:
204: if (obj instanceof Db4oTypeImpl) {
205: depth = ((Db4oTypeImpl) obj).adjustReadDepth(depth);
206: }
207:
208: // this is OK for primitive YapAnys. They will not be added
209: // to the list, since they will not be found in the ID tree.
210: container().stillToActivate(transaction(), obj, depth);
211:
212: return obj;
213: }
214:
215: private boolean peekPersisted() {
216: return _addToIDTree == Const4.TRANSIENT;
217: }
218:
219: public Object readObject(TypeHandler4 handlerType) {
220: TypeHandler4 handler = correctHandlerVersion(handlerType);
221: if (!isIndirected(handler)) {
222: return handler.read(this );
223: }
224: int payLoadOffset = readInt();
225: readInt(); // length - never used
226: if (payLoadOffset == 0) {
227: return null;
228: }
229: int savedOffset = offset();
230: seek(payLoadOffset);
231: Object obj = handler.read(this );
232: seek(savedOffset);
233: return obj;
234: }
235:
236: public void adjustInstantiationDepth() {
237: Config4Class classConfig = classConfig();
238: if (classConfig != null) {
239: _activationDepth = classConfig
240: .adjustActivationDepth(_activationDepth);
241: }
242: }
243:
244: public Config4Class classConfig() {
245: return classMetadata().config();
246: }
247:
248: public ObjectReference reference() {
249: return _reference;
250: }
251:
252: public void addToIDTree() {
253: if (_addToIDTree == Const4.ADD_TO_ID_TREE) {
254: _reference.addExistingReferenceToIdTree(transaction());
255: }
256: }
257:
258: public void persistentObject(Object obj) {
259: _object = obj;
260: }
261:
262: public ObjectHeaderAttributes headerAttributes() {
263: return _objectHeader._headerAttributes;
264: }
265:
266: public boolean isNull(int fieldIndex) {
267: return headerAttributes().isNull(fieldIndex);
268: }
269:
270: public int handlerVersion() {
271: return _objectHeader.handlerVersion();
272: }
273:
274: }
|