/* 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.*; import com.db4o.foundation.*; import com.db4o.internal.*; import com.db4o.internal.encoding.*; /** * @exclude */ public abstract class ClassMarshaller { public MarshallerFamily _family; public RawClassSpec readSpec(Transaction trans,ByteArrayBuffer reader) { byte[] nameBytes=readName(trans, reader); String className=trans.container().stringIO().read(nameBytes); readMetaClassID(reader); // skip int ancestorID=reader.readInt(); reader.incrementOffset(Const4.INT_LENGTH); // index ID int numFields=reader.readInt(); return new RawClassSpec(className,ancestorID,numFields); } public void write(final Transaction trans, final ClassMetadata clazz, final ByteArrayBuffer writer) { writer.writeShortString(trans, clazz.nameToWrite()); int intFormerlyKnownAsMetaClassID = 0; writer.writeInt(intFormerlyKnownAsMetaClassID); writer.writeIDOf(trans, clazz._ancestor); writeIndex(trans, clazz, writer); writer.writeInt(clazz.declaredAspectCount()); clazz.traverseDeclaredAspects(new Procedure4() { public void apply(Object arg) { _family._field.write(trans, clazz, (ClassAspect)arg, writer); } }); } protected void writeIndex(Transaction trans, ClassMetadata clazz, ByteArrayBuffer writer) { int indexID = clazz.index().write(trans); writer.writeInt(indexIDForWriting(indexID)); } protected abstract int indexIDForWriting(int indexID); public final byte[] readName(Transaction trans, ByteArrayBuffer reader) { return readName(trans.container().stringIO(), reader); } public final int readMetaClassID(ByteArrayBuffer reader) { return reader.readInt(); } private byte[] readName(LatinStringIO sio, ByteArrayBuffer reader) { if (Deploy.debug) { reader.readBegin(Const4.YAPCLASS); } byte[] nameBytes = sio.bytes(reader); reader.incrementOffset(nameBytes.length); nameBytes = Platform4.updateClassName(nameBytes); return nameBytes; } public final void read(ObjectContainerBase stream, ClassMetadata clazz, ByteArrayBuffer reader) { clazz.setAncestor(stream.classMetadataForID(reader.readInt())); // if(clazz.callConstructor()){ // // The logic further down checks the ancestor YapClass, whether // // or not it is allowed, not to call constructors. The ancestor // // YapClass may possibly have not been loaded yet. // clazz.createConstructor(true); // } clazz.checkType(); readIndex(stream, clazz, reader); clazz._aspects = readAspects(stream, reader, clazz); } protected abstract void readIndex(ObjectContainerBase stream, ClassMetadata clazz, ByteArrayBuffer reader) ; private ClassAspect[] readAspects(ObjectContainerBase stream, ByteArrayBuffer reader, final ClassMetadata clazz) { ClassAspect[] aspects = new ClassAspect[reader.readInt()]; for (int i = 0; i < aspects.length; i++) { aspects[i] = _family._field.read(stream, clazz, reader); aspects[i].setHandle(i); } return aspects; } public int marshalledLength(final ObjectContainerBase stream, final ClassMetadata clazz) { final IntByRef len = new IntByRef( stream.stringIO().shortLength(clazz.nameToWrite()) + Const4.OBJECT_LENGTH + (Const4.INT_LENGTH * 2) + (Const4.ID_LENGTH)); len.value += clazz.index().ownLength(); clazz.traverseDeclaredAspects(new Procedure4() { public void apply(Object arg) { len.value += _family._field.marshalledLength(stream, (ClassAspect)arg); } }); return len.value; } public void defrag(final ClassMetadata classMetadata, final LatinStringIO sio, final DefragmentContextImpl context, int classIndexID) { readName(sio, context.sourceBuffer()); readName(sio, context.targetBuffer()); int metaClassID=0; context.writeInt(metaClassID); // ancestor ID context.copyID(); context.writeInt((classMetadata.hasClassIndex() ? indexIDForWriting(classIndexID) : 0)); final int aspectCount = context.readInt(); if(aspectCount > classMetadata.declaredAspectCount()) { throw new IllegalStateException(); } final IntByRef processedAspectCount = new IntByRef(0); classMetadata.traverseDeclaredAspects(new Procedure4() { public void apply(Object arg) { if(processedAspectCount.value >= aspectCount){ return; } ClassAspect aspect = (ClassAspect) arg; _family._field.defrag(classMetadata,aspect,sio,context); processedAspectCount.value++; } }); } }