private NeoDatis.Odb.Core.Layers.Layer2.Meta.ArrayObjectInfo IntropectAtomicNativeArray
            (object array, NeoDatis.Odb.Core.Layers.Layer2.Meta.ODBType type)
        {
            int length = NeoDatis.Tool.Wrappers.OdbReflection.GetArrayLength(array);

            NeoDatis.Odb.Core.Layers.Layer2.Meta.AtomicNativeObjectInfo anoi = null;
            object[] arrayCopy = new object[length];
            int      typeId    = 0;

            for (int i = 0; i < length; i++)
            {
                object o = NeoDatis.Tool.Wrappers.OdbReflection.GetArrayElement(array, i);
                if (o != null)
                {
                    // If object is not null, try to get the exact type
                    typeId = NeoDatis.Odb.Core.Layers.Layer2.Meta.ODBType.GetFromClass(o.GetType()).GetId
                                 ();
                    anoi         = new NeoDatis.Odb.Core.Layers.Layer2.Meta.AtomicNativeObjectInfo(o, typeId);
                    arrayCopy[i] = anoi;
                }
                else
                {
                    // Else take the declared type
                    arrayCopy[i] = new NeoDatis.Odb.Core.Layers.Layer2.Meta.NullNativeObjectInfo(type
                                                                                                 .GetId());
                }
            }
            NeoDatis.Odb.Core.Layers.Layer2.Meta.ArrayObjectInfo aoi = new NeoDatis.Odb.Core.Layers.Layer2.Meta.ArrayObjectInfo
                                                                           (arrayCopy, NeoDatis.Odb.Core.Layers.Layer2.Meta.ODBType.Array, type.GetId());
            return(aoi);
        }
 protected virtual NeoDatis.Odb.Core.Layers.Layer2.Meta.AbstractObjectInfo GetNativeObjectInfoInternal
     (NeoDatis.Odb.Core.Layers.Layer2.Meta.ODBType type, object o, bool recursive
     , System.Collections.Generic.IDictionary <object, NeoDatis.Odb.Core.Layers.Layer2.Meta.NonNativeObjectInfo
                                               > alreadyReadObjects, NeoDatis.Odb.Core.Layers.Layer1.Introspector.IIntrospectionCallback
     callback)
 {
     NeoDatis.Odb.Core.Layers.Layer2.Meta.AbstractObjectInfo aoi = null;
     if (type.IsAtomicNative())
     {
         if (o == null)
         {
             aoi = new NeoDatis.Odb.Core.Layers.Layer2.Meta.NullNativeObjectInfo(type.GetId());
         }
         else
         {
             aoi = new NeoDatis.Odb.Core.Layers.Layer2.Meta.AtomicNativeObjectInfo(o, type
                                                                                   .GetId());
         }
     }
     else
     {
         if (type.IsCollection())
         {
             aoi = IntrospectCollection((System.Collections.ICollection)o, recursive, alreadyReadObjects
                                        , type, callback);
         }
         else
         {
             if (type.IsArray())
             {
                 if (o == null)
                 {
                     aoi = new NeoDatis.Odb.Core.Layers.Layer2.Meta.ArrayObjectInfo(null);
                 }
                 else
                 {
                     // Gets the type of the elements of the array
                     string realArrayClassName = OdbClassUtil.GetFullName(o.GetType().GetElementType());
                     NeoDatis.Odb.Core.Layers.Layer2.Meta.ArrayObjectInfo aroi = null;
                     if (recursive)
                     {
                         aroi = IntrospectArray(o, recursive, alreadyReadObjects, type, callback);
                     }
                     else
                     {
                         aroi = new NeoDatis.Odb.Core.Layers.Layer2.Meta.ArrayObjectInfo((object[])o
                                                                                         );
                     }
                     aroi.SetRealArrayComponentClassName(realArrayClassName);
                     aoi = aroi;
                 }
             }
             else
             {
                 if (type.IsMap())
                 {
                     if (o == null)
                     {
                         aoi = new NeoDatis.Odb.Core.Layers.Layer2.Meta.MapObjectInfo(null, type, type.GetDefaultInstanciationClass
                                                                                          ().FullName);
                     }
                     else
                     {
                         MapObjectInfo moi = null;
                         string        realMapClassName = OdbClassUtil.GetFullName(o.GetType());
                         bool          isGeneric        = o.GetType().IsGenericType;
                         if (isGeneric)
                         {
                             moi = new MapObjectInfo(IntrospectGenericMap((System.Collections.Generic.IDictionary <object, object>)o, recursive, alreadyReadObjects, callback), type, realMapClassName);
                         }
                         else
                         {
                             moi = new MapObjectInfo(IntrospectNonGenericMap((System.Collections.IDictionary)o, recursive, alreadyReadObjects, callback), type, realMapClassName);
                         }
                         if (realMapClassName.IndexOf("$") != -1)
                         {
                             moi.SetRealMapClassName(OdbClassUtil.GetFullName(type.GetDefaultInstanciationClass()));
                         }
                         aoi = moi;
                     }
                 }
                 else
                 {
                     if (type.IsEnum())
                     {
                         System.Enum enumObject = (System.Enum)o;
                         if (enumObject == null)
                         {
                             aoi = new NeoDatis.Odb.Core.Layers.Layer2.Meta.NullNativeObjectInfo(type.GetSize(
                                                                                                     ));
                         }
                         else
                         {
                             Type   t             = enumObject.GetType();
                             string enumClassName = enumObject == null ? null : OdbClassUtil.GetFullName(enumObject.GetType());
                             // Here we must check if the enum is already in the meta model. Enum must be stored in the meta
                             // model to optimize its storing as we need to keep track of the enum class
                             // for each enum stored. So instead of storing the enum class name, we can store enum class id, a long
                             // instead of the full enum class name string
                             NeoDatis.Odb.Core.Layers.Layer2.Meta.ClassInfo ci = GetClassInfo(enumClassName);
                             string enumValue = enumObject == null ? null : enumObject.ToString();
                             aoi = new NeoDatis.Odb.Core.Layers.Layer2.Meta.EnumNativeObjectInfo(ci, enumValue
                                                                                                 );
                         }
                     }
                 }
             }
         }
     }
     return(aoi);
 }
		protected virtual NeoDatis.Odb.Core.Layers.Layer2.Meta.AbstractObjectInfo GetNativeObjectInfoInternal
			(NeoDatis.Odb.Core.Layers.Layer2.Meta.ODBType type, object o, bool recursive
			, System.Collections.Generic.IDictionary<object, NeoDatis.Odb.Core.Layers.Layer2.Meta.NonNativeObjectInfo
			> alreadyReadObjects, NeoDatis.Odb.Core.Layers.Layer1.Introspector.IIntrospectionCallback
			 callback)
		{
			NeoDatis.Odb.Core.Layers.Layer2.Meta.AbstractObjectInfo aoi = null;
			if (type.IsAtomicNative())
			{
				if (o == null)
				{
					aoi = new NeoDatis.Odb.Core.Layers.Layer2.Meta.NullNativeObjectInfo(type.GetId());
				}
				else
				{
					aoi = new NeoDatis.Odb.Core.Layers.Layer2.Meta.AtomicNativeObjectInfo(o, type
						.GetId());
				}
			}
			else
			{
				if (type.IsCollection())
				{
					aoi = IntrospectCollection((System.Collections.ICollection)o, recursive, alreadyReadObjects
						, type, callback);
				}
				else
				{
					if (type.IsArray())
					{
						if (o == null)
						{
							aoi = new NeoDatis.Odb.Core.Layers.Layer2.Meta.ArrayObjectInfo(null);
						}
						else
						{
							// Gets the type of the elements of the array
							string realArrayClassName = OdbClassUtil.GetFullName(o.GetType().GetElementType());
							NeoDatis.Odb.Core.Layers.Layer2.Meta.ArrayObjectInfo aroi = null;
							if (recursive)
							{
								aroi = IntrospectArray(o, recursive, alreadyReadObjects, type, callback);
							}
							else
							{
								aroi = new NeoDatis.Odb.Core.Layers.Layer2.Meta.ArrayObjectInfo((object[])o
									);
							}
							aroi.SetRealArrayComponentClassName(realArrayClassName);
							aoi = aroi;
						}
					}
					else
					{
						if (type.IsMap())
						{
							if (o == null)
							{
								aoi = new NeoDatis.Odb.Core.Layers.Layer2.Meta.MapObjectInfo(null, type, type.GetDefaultInstanciationClass
									().FullName);
							}
							else
							{
								MapObjectInfo moi = null;
								string realMapClassName = OdbClassUtil.GetFullName(o.GetType());
                                bool isGeneric = o.GetType().IsGenericType;
                                if (isGeneric)
                                {
                                    moi = new MapObjectInfo(IntrospectGenericMap((System.Collections.Generic.IDictionary<object,object>)o, recursive, alreadyReadObjects, callback), type, realMapClassName);
                                }
                                else
                                {
                                    moi = new MapObjectInfo(IntrospectNonGenericMap((System.Collections.IDictionary)o, recursive, alreadyReadObjects, callback), type, realMapClassName);
                                }
								if (realMapClassName.IndexOf("$") != -1)
								{
									moi.SetRealMapClassName(OdbClassUtil.GetFullName(type.GetDefaultInstanciationClass()));
								}
								aoi = moi;
							}
						}
						else
						{
							if (type.IsEnum())
							{
								System.Enum enumObject = (System.Enum)o;
								if (enumObject == null)
								{
									aoi = new NeoDatis.Odb.Core.Layers.Layer2.Meta.NullNativeObjectInfo(type.GetSize(
										));
								}
								else
								{
                                    Type t = enumObject.GetType();
                                    string enumClassName = enumObject == null ? null : OdbClassUtil.GetFullName(enumObject.GetType());
									// Here we must check if the enum is already in the meta model. Enum must be stored in the meta
									// model to optimize its storing as we need to keep track of the enum class
									// for each enum stored. So instead of storing the enum class name, we can store enum class id, a long
									// instead of the full enum class name string
									NeoDatis.Odb.Core.Layers.Layer2.Meta.ClassInfo ci = GetClassInfo(enumClassName);
									string enumValue = enumObject == null ? null : enumObject.ToString();
									aoi = new NeoDatis.Odb.Core.Layers.Layer2.Meta.EnumNativeObjectInfo(ci, enumValue
										);
								}
							}
						}
					}
				}
			}
			return aoi;
		}
		private NeoDatis.Odb.Core.Layers.Layer2.Meta.ArrayObjectInfo IntropectAtomicNativeArray
			(object array, NeoDatis.Odb.Core.Layers.Layer2.Meta.ODBType type)
		{
			int length = NeoDatis.Tool.Wrappers.OdbReflection.GetArrayLength(array);
			NeoDatis.Odb.Core.Layers.Layer2.Meta.AtomicNativeObjectInfo anoi = null;
			object[] arrayCopy = new object[length];
			int typeId = 0;
			for (int i = 0; i < length; i++)
			{
				object o = NeoDatis.Tool.Wrappers.OdbReflection.GetArrayElement(array, i);
				if (o != null)
				{
					// If object is not null, try to get the exact type
					typeId = NeoDatis.Odb.Core.Layers.Layer2.Meta.ODBType.GetFromClass(o.GetType()).GetId
						();
					anoi = new NeoDatis.Odb.Core.Layers.Layer2.Meta.AtomicNativeObjectInfo(o, typeId);
					arrayCopy[i] = anoi;
				}
				else
				{
					// Else take the declared type
					arrayCopy[i] = new NeoDatis.Odb.Core.Layers.Layer2.Meta.NullNativeObjectInfo(type
						.GetId());
				}
			}
			NeoDatis.Odb.Core.Layers.Layer2.Meta.ArrayObjectInfo aoi = new NeoDatis.Odb.Core.Layers.Layer2.Meta.ArrayObjectInfo
				(arrayCopy, NeoDatis.Odb.Core.Layers.Layer2.Meta.ODBType.Array, type.GetId());
			return aoi;
		}
		public virtual NeoDatis.Odb.OID WriteNonNativeObjectInfo(NeoDatis.Odb.OID existingOid
			, NeoDatis.Odb.Core.Layers.Layer2.Meta.NonNativeObjectInfo objectInfo, long position
			, bool writeDataInTransaction, bool isNewObject)
		{
			NeoDatis.Odb.Core.Transaction.ISession lsession = GetSession();
			NeoDatis.Odb.Core.Transaction.ICache cache = lsession.GetCache();
			bool hasObject = objectInfo.GetObject() != null;
			// Insert triggers for CS Mode, local mode insert triggers are called in the DefaultInstrumentationCallbackForStore class
			if (isNewObject && !isLocalMode)
			{
				triggerManager.ManageInsertTriggerBefore(objectInfo.GetClassInfo().GetFullClassName
					(), objectInfo);
			}
			// Checks if object is null,for null objects,there is nothing to do
			if (objectInfo.IsNull())
			{
				return NeoDatis.Odb.Impl.Core.Layers.Layer3.Engine.StorageEngineConstant.NullObjectId;
			}
			NeoDatis.Odb.Core.Layers.Layer2.Meta.MetaModel metaModel = lsession.GetMetaModel(
				);
			// first checks if the class of this object already exist in the
			// metamodel
			if (!metaModel.ExistClass(objectInfo.GetClassInfo().GetFullClassName()))
			{
				AddClass(objectInfo.GetClassInfo(), true);
			}
			// if position is -1, gets the position where to write the object
			if (position == -1)
			{
				// Write at the end of the file
				position = fsi.GetAvailablePosition();
				// Updates the meta object position
				objectInfo.SetPosition(position);
			}
			// Gets the object id
			NeoDatis.Odb.OID oid = existingOid;
			if (oid == null)
			{
				// If, to get the next id, a new id block must be created, then
				// there is an extra work
				// to update the current object position
				if (idManager.MustShift())
				{
					oid = idManager.GetNextObjectId(position);
					// The id manager wrote in the file so the position for the
					// object must be re-computed
					position = fsi.GetAvailablePosition();
					// The oid must be associated to this new position - id
					// operations are always out of transaction
					// in this case, the update is done out of the transaction as a
					// rollback won t need to
					// undo this. We are just creating the id
					// => third parameter(write in transaction) = false
					idManager.UpdateObjectPositionForOid(oid, position, false);
				}
				else
				{
					oid = idManager.GetNextObjectId(position);
				}
			}
			else
			{
				// If an oid was passed, it is because object already exist and
				// is being updated. So we
				// must update the object position
				// Here the update of the position of the id must be done in
				// transaction as the object
				// position of the id is being updated, and a rollback should undo
				// this
				// => third parameter(write in transaction) = true
				idManager.UpdateObjectPositionForOid(oid, position, true);
				// Keep the relation of id and position in the cache until the
				// commit
				cache.SavePositionOfObjectWithOid(oid, position);
			}
			// Sets the oid of the object in the inserting cache
			cache.UpdateIdOfInsertingObject(objectInfo.GetObject(), oid);
			// Only add the oid to unconnected zone if it is a new object
			if (isNewObject)
			{
				cache.AddOIDToUnconnectedZone(oid);
				if (NeoDatis.Odb.OdbConfiguration.ReconnectObjectsToSession())
				{
					NeoDatis.Odb.Core.Transaction.ICrossSessionCache crossSessionCache = NeoDatis.Odb.Impl.Core.Transaction.CacheFactory
						.GetCrossSessionCache(storageEngine.GetBaseIdentification().GetIdentification());
					crossSessionCache.AddObject(objectInfo.GetObject(), oid);
				}
			}
			objectInfo.SetOid(oid);
			if (NeoDatis.Odb.OdbConfiguration.IsDebugEnabled(LogId))
			{
				NeoDatis.Tool.DLogger.Debug(DepthToSpaces() + "Start Writing non native object of type "
					 + objectInfo.GetClassInfo().GetFullClassName() + " at " + position + " , oid = "
					 + oid + " : " + objectInfo.ToString());
			}
			if (objectInfo.GetClassInfo() == null || objectInfo.GetClassInfo().GetId() == null)
			{
				if (objectInfo.GetClassInfo() != null)
				{
					NeoDatis.Odb.Core.Layers.Layer2.Meta.ClassInfo clinfo = storageEngine.GetSession(
						true).GetMetaModel().GetClassInfo(objectInfo.GetClassInfo().GetFullClassName(), 
						true);
					objectInfo.SetClassInfo(clinfo);
				}
				else
				{
					throw new NeoDatis.Odb.ODBRuntimeException(NeoDatis.Odb.Core.NeoDatisError.UndefinedClassInfo
						.AddParameter(objectInfo.ToString()));
				}
			}
			// updates the meta model - If class already exist, it returns the
			// metamodel class, which contains
			// a bit more informations
			NeoDatis.Odb.Core.Layers.Layer2.Meta.ClassInfo classInfo = AddClass(objectInfo.GetClassInfo
				(), true);
			objectInfo.SetClassInfo(classInfo);
			// 
			if (isNewObject)
			{
				ManageNewObjectPointers(objectInfo, classInfo, position, metaModel);
			}
			if (NeoDatis.Odb.OdbConfiguration.SaveHistory())
			{
				classInfo.AddHistory(new NeoDatis.Odb.Impl.Core.Layers.Layer2.Meta.History.InsertHistoryInfo
					("insert", oid, position, objectInfo.GetPreviousObjectOID(), objectInfo.GetNextObjectOID
					()));
			}
			fsi.SetWritePosition(position, writeDataInTransaction);
			objectInfo.SetPosition(position);
			int nbAttributes = objectInfo.GetClassInfo().GetAttributes().Count;
			// compute the size of the array of byte needed till the attibute
			// positions
			// BlockSize + Block Type + ObjectId + ClassInfoId + Previous + Next +
			// CreatDate + UpdateDate + VersionNumber + ObjectRef + isSync + NbAttri
			// + Attributes
			// Int + Int + Long + Long + Long + Long + Long + Long + int + Long +
			// Bool + int + variable
			// 7 Longs + 4Ints + 1Bool + variable
			int tsize = 7 * NeoDatis.Odb.Core.Layers.Layer2.Meta.ODBType.SizeOfLong + 3 * NeoDatis.Odb.Core.Layers.Layer2.Meta.ODBType
				.SizeOfInt + 2 * NeoDatis.Odb.Core.Layers.Layer2.Meta.ODBType.SizeOfByte;
			byte[] bytes = new byte[tsize];
			// Block size
			byteArrayConverter.IntToByteArray(0, bytes, 0);
			// Block type
			bytes[4] = NeoDatis.Odb.Impl.Core.Layers.Layer3.Block.BlockTypes.BlockTypeNonNativeObject;
			// fsi.writeInt(BlockTypes.BLOCK_TYPE_NON_NATIVE_OBJECT,
			// writeDataInTransaction, "block size");
			// The object id
			EncodeOid(oid, bytes, 5);
			// fsi.writeLong(oid.getObjectId(), writeDataInTransaction, "oid",
			// DefaultWriteAction.DATA_WRITE_ACTION);
			// Class info id
			byteArrayConverter.LongToByteArray(classInfo.GetId().GetObjectId(), bytes, 13);
			// fsi.writeLong(classInfo.getId().getObjectId(),
			// writeDataInTransaction, "class info id",
			// DefaultWriteAction.DATA_WRITE_ACTION);
			// previous instance
			EncodeOid(objectInfo.GetPreviousObjectOID(), bytes, 21);
			// writeOid(objectInfo.getPreviousObjectOID(), writeDataInTransaction,
			// "prev instance", DefaultWriteAction.DATA_WRITE_ACTION);
			// next instance
			EncodeOid(objectInfo.GetNextObjectOID(), bytes, 29);
			// writeOid(objectInfo.getNextObjectOID(), writeDataInTransaction,
			// "next instance", DefaultWriteAction.DATA_WRITE_ACTION);
			// creation date, for update operation must be the original one
			byteArrayConverter.LongToByteArray(objectInfo.GetHeader().GetCreationDate(), bytes
				, 37);
			// fsi.writeLong(objectInfo.getHeader().getCreationDate(),
			// writeDataInTransaction, "creation date",
			// DefaultWriteAction.DATA_WRITE_ACTION);
			byteArrayConverter.LongToByteArray(NeoDatis.Tool.Wrappers.OdbTime.GetCurrentTimeInMs
				(), bytes, 45);
			// fsi.writeLong(OdbTime.getCurrentTimeInMs(), writeDataInTransaction,
			// "update date", DefaultWriteAction.DATA_WRITE_ACTION);
			// TODO check next version number
			byteArrayConverter.IntToByteArray(objectInfo.GetHeader().GetObjectVersion(), bytes
				, 53);
			// fsi.writeInt(objectInfo.getHeader().getObjectVersion(),
			// writeDataInTransaction, "object version number");
			// not used yet. But it will point to an internal object of type
			// ObjectReference that will have details on the references:
			// All the objects that point to it: to enable object integrity
			byteArrayConverter.LongToByteArray(-1, bytes, 57);
			// fsi.writeLong(-1, writeDataInTransaction, "object reference pointer",
			// DefaultWriteAction.DATA_WRITE_ACTION);
			// True if this object have been synchronized with main database, else
			// false
			byteArrayConverter.BooleanToByteArray(false, bytes, 65);
			// fsi.writeBoolean(false, writeDataInTransaction,
			// "is syncronized with external db");
			// now write the number of attributes and the position of all
			// attributes, we do not know them yet, so write 00 but at the end
			// of the write operation
			// These positions will be updated
			// The positions that is going to be written are 'int' representing
			// the offset position of the attribute
			// first write the number of attributes
			// fsi.writeInt(nbAttributes, writeDataInTransaction, "nb attr");
			byteArrayConverter.IntToByteArray(nbAttributes, bytes, 66);
			// Then write the array of bytes
			fsi.WriteBytes(bytes, writeDataInTransaction, "NonNativeObjectInfoHeader");
			// Store the position
			long attributePositionStart = fsi.GetPosition();
			int attributeSize = NeoDatis.Odb.Core.Layers.Layer2.Meta.ODBType.SizeOfInt + NeoDatis.Odb.Core.Layers.Layer2.Meta.ODBType
				.SizeOfLong;
			byte[] abytes = new byte[nbAttributes * (attributeSize)];
			// here, just write an empty (0) array, as real values will be set at
			// the end
			fsi.WriteBytes(abytes, writeDataInTransaction, "Empty Attributes");
			long[] attributesIdentification = new long[nbAttributes];
			int[] attributeIds = new int[nbAttributes];
			// Puts the object info in the cache
			// storageEngine.getSession().getCache().addObject(position,
			// aoi.getObject(), objectInfo.getHeader());
			NeoDatis.Odb.Core.Layers.Layer2.Meta.ClassAttributeInfo cai = null;
			NeoDatis.Odb.Core.Layers.Layer2.Meta.AbstractObjectInfo aoi2 = null;
			long nativeAttributePosition = -1;
			NeoDatis.Odb.OID nonNativeAttributeOid = null;
			long maxWritePosition = fsi.GetPosition();
			// Loop on all attributes
			for (int i = 0; i < nbAttributes; i++)
			{
				// Gets the attribute meta description
				cai = classInfo.GetAttributeInfo(i);
				// Gets the id of the attribute
				attributeIds[i] = cai.GetId();
				// Gets the attribute data
				aoi2 = objectInfo.GetAttributeValueFromId(cai.GetId());
				if (aoi2 == null)
				{
					// This only happens in 1 case : when a class has a field with
					// the same name of one of is superclass. In this, the deeper
					// attribute is null
					if (cai.IsNative())
					{
						aoi2 = new NeoDatis.Odb.Core.Layers.Layer2.Meta.NullNativeObjectInfo(cai.GetAttributeType
							().GetId());
					}
					else
					{
						aoi2 = new NeoDatis.Odb.Core.Layers.Layer2.Meta.NonNativeNullObjectInfo(cai.GetClassInfo
							());
					}
				}
				if (aoi2.IsNative())
				{
					nativeAttributePosition = InternalStoreObject((NeoDatis.Odb.Core.Layers.Layer2.Meta.NativeObjectInfo
						)aoi2);
					// For native objects , odb stores their position
					attributesIdentification[i] = nativeAttributePosition;
				}
				else
				{
					if (aoi2.IsObjectReference())
					{
						NeoDatis.Odb.Core.Layers.Layer2.Meta.ObjectReference or = (NeoDatis.Odb.Core.Layers.Layer2.Meta.ObjectReference
							)aoi2;
						nonNativeAttributeOid = or.GetOid();
					}
					else
					{
						nonNativeAttributeOid = StoreObject(null, (NeoDatis.Odb.Core.Layers.Layer2.Meta.NonNativeObjectInfo
							)aoi2);
					}
					// For non native objects , odb stores its oid as a negative
					// number!!u
					if (nonNativeAttributeOid != null)
					{
						attributesIdentification[i] = -nonNativeAttributeOid.GetObjectId();
					}
					else
					{
						attributesIdentification[i] = NeoDatis.Odb.Impl.Core.Layers.Layer3.Engine.StorageEngineConstant
							.NullObjectIdId;
					}
				}
				long p = fsi.GetPosition();
				if (p > maxWritePosition)
				{
					maxWritePosition = p;
				}
			}
			// Updates attributes identification in the object info header
			objectInfo.GetHeader().SetAttributesIdentification(attributesIdentification);
			objectInfo.GetHeader().SetAttributesIds(attributeIds);
			long positionAfterWrite = maxWritePosition;
			// Now writes back the attribute positions
			fsi.SetWritePosition(attributePositionStart, writeDataInTransaction);
			abytes = new byte[attributesIdentification.Length * (attributeSize)];
			for (int i = 0; i < attributesIdentification.Length; i++)
			{
				byteArrayConverter.IntToByteArray(attributeIds[i], abytes, i * attributeSize);
				byteArrayConverter.LongToByteArray(attributesIdentification[i], abytes, i * (attributeSize
					) + NeoDatis.Odb.Core.Layers.Layer2.Meta.ODBType.SizeOfInt);
				// fsi.writeInt(attributeIds[i], writeDataInTransaction, "attr id");
				// fsi.writeLong(attributesIdentification[i],
				// writeDataInTransaction, "att real pos",
				// DefaultWriteAction.DATA_WRITE_ACTION);
				// if (classInfo.getAttributeInfo(i).isNonNative() &&
				// attributesIdentification[i] > 0) {
				if (objectInfo.GetAttributeValueFromId(attributeIds[i]).IsNonNativeObject() && attributesIdentification
					[i] > 0)
				{
					throw new NeoDatis.Odb.ODBRuntimeException(NeoDatis.Odb.Core.NeoDatisError.NonNativeAttributeStoredByPositionInsteadOfOid
						.AddParameter(classInfo.GetAttributeInfo(i).GetName()).AddParameter(classInfo.GetFullClassName
						()).AddParameter(attributesIdentification[i]));
				}
			}
			fsi.WriteBytes(abytes, writeDataInTransaction, "Filled Attributes");
			fsi.SetWritePosition(positionAfterWrite, writeDataInTransaction);
			int blockSize = (int)(positionAfterWrite - position);
			try
			{
				WriteBlockSizeAt(position, blockSize, writeDataInTransaction, objectInfo);
			}
			catch (NeoDatis.Odb.ODBRuntimeException e)
			{
				NeoDatis.Tool.DLogger.Debug("Error while writing block size. pos after write " + 
					positionAfterWrite + " / start pos = " + position);
				// throw new ODBRuntimeException(storageEngine,"Error while writing
				// block size. pos after write " + positionAfterWrite + " / start
				// pos = " + position,e);
				throw;
			}
			if (NeoDatis.Odb.OdbConfiguration.IsDebugEnabled(LogId))
			{
				NeoDatis.Tool.DLogger.Debug(DepthToSpaces() + "  Attributes positions of object with oid "
					 + oid + " are " + NeoDatis.Tool.DisplayUtility.LongArrayToString(attributesIdentification
					));
				NeoDatis.Tool.DLogger.Debug(DepthToSpaces() + "End Writing non native object at "
					 + position + " with oid " + oid + " - prev oid=" + objectInfo.GetPreviousObjectOID
					() + " / next oid=" + objectInfo.GetNextObjectOID());
				if (NeoDatis.Odb.OdbConfiguration.IsDebugEnabled(LogIdDebug))
				{
					NeoDatis.Tool.DLogger.Debug(" - current buffer : " + fsi.GetIo().ToString());
				}
			}
			// Only insert in index for new objects
			if (isNewObject)
			{
				// insert object id in indexes, if exist
				ManageIndexesForInsert(oid, objectInfo);
				if (hasObject)
				{
					triggerManager.ManageInsertTriggerAfter(objectInfo.GetClassInfo().GetFullClassName
						(), objectInfo.GetObject(), oid);
				}
				else
				{
					// triggers
					triggerManager.ManageInsertTriggerAfter(objectInfo.GetClassInfo().GetFullClassName
						(), objectInfo, oid);
				}
			}
			return oid;
		}