Example #1
0
        public override object GetObjectFromOid(NeoDatis.Odb.OID oid)
        {
            if (oid == null)
            {
                throw new NeoDatis.Odb.ODBRuntimeException(NeoDatis.Odb.Core.NeoDatisError.CanNotGetObjectFromNullOid
                                                           );
            }
            NeoDatis.Odb.Core.Layers.Layer2.Meta.NonNativeObjectInfo nnoi = GetObjectReader()
                                                                            .ReadNonNativeObjectInfoFromOid(null, oid, true, true);
            if (nnoi.IsDeletedObject())
            {
                throw new NeoDatis.Odb.ODBRuntimeException(NeoDatis.Odb.Core.NeoDatisError.ObjectIsMarkedAsDeletedForOid
                                                           .AddParameter(oid));
            }
            object o = nnoi.GetObject();

            if (o == null)
            {
                o = GetObjectReader().GetInstanceBuilder().BuildOneInstance(nnoi);
            }
            NeoDatis.Odb.Core.Transaction.ISession lsession = GetSession(true);
            // Here oid can be different from nnoi.getOid(). This is the case when
            // the oid is an external oid. That`s why we use
            // nnoi.getOid() to put in the cache
            lsession.GetCache().AddObject(nnoi.GetOid(), o, nnoi.GetHeader());
            lsession.GetTmpCache().ClearObjectInfos();
            return(o);
        }
		/// <summary>
		/// Checks if something in the Collection has changed, if yes, stores the
		/// change
		/// </summary>
		/// <param name="nnoi1">
		/// The first Object meta representation (nnoi =
		/// NonNativeObjectInfo)
		/// </param>
		/// <param name="nnoi2">The second object meta representation</param>
		/// <param name="fieldIndex">The field index that this collection represents</param>
		/// <param name="coi1">
		/// The Meta representation of the collection 1 (coi =
		/// CollectionObjectInfo)
		/// </param>
		/// <param name="coi2">The Meta representation of the collection 2</param>
		/// <param name="objectRecursionLevel"></param>
		/// <returns>true if 2 collection representation are different</returns>
		private bool ManageCollectionChanges(NonNativeObjectInfo
			 nnoi1, NonNativeObjectInfo nnoi2, int fieldId
			, CollectionObjectInfo coi1, CollectionObjectInfo
			 coi2, int objectRecursionLevel)
		{
			ICollection<AbstractObjectInfo
				> collection1 = coi1.GetCollection();
			ICollection<AbstractObjectInfo
				> collection2 = coi2.GetCollection();
			if (collection1.Count != collection2.Count)
			{
				System.Text.StringBuilder buffer = new System.Text.StringBuilder();
				buffer.Append("Collection size has changed oldsize=").Append(collection1.Count).Append
					("/newsize=").Append(collection2.Count);
				StoreChangedObject(nnoi1, nnoi2, fieldId, coi1, coi2, buffer.ToString(), objectRecursionLevel
					);
				return true;
			}
			System.Collections.IEnumerator iterator1 = collection1.GetEnumerator();
			System.Collections.IEnumerator iterator2 = collection2.GetEnumerator();
			AbstractObjectInfo value1 = null;
			AbstractObjectInfo value2 = null;
			int index = 0;
			while (iterator1.MoveNext())
			{
                iterator2.MoveNext();
                value1 = (AbstractObjectInfo)iterator1.Current;
				value2 = (AbstractObjectInfo)iterator2.Current;
				bool hasChanged = this.HasChanged(value1, value2, objectRecursionLevel);
				if (hasChanged)
				{
					// We consider collection has changed only if object are
					// different, If objects are the same instance, but something in
					// the object has changed, then the collection has not
					// changed,only the object
					if (value1.IsNonNativeObject() && value2.IsNonNativeObject())
					{
						NonNativeObjectInfo nnoia = (NonNativeObjectInfo
							)value1;
						NonNativeObjectInfo nnoib = (NonNativeObjectInfo
							)value2;
						if (nnoia.GetOid() != null && !nnoia.GetOid().Equals(nnoi2.GetOid()))
						{
							// Objects are not the same instance -> the collection
							// has changed
							StoreChangedObject(nnoi1, nnoi2, fieldId, value1, value2, "List element index " +
								 index + " has changed", objectRecursionLevel);
						}
					}
					else
					{
						supportInPlaceUpdate = false;
						nbChanges++;
					}
					//storeChangedObject(nnoi1, nnoi2, fieldId, value1, value2, "List element index " + index + " has changed", objectRecursionLevel);
					return true;
				}
				index++;
			}
			return false;
		}
		private void StoreChangedObject(NonNativeObjectInfo
			 aoi1, NonNativeObjectInfo aoi2, int fieldId
			, AbstractObjectInfo oldValue, AbstractObjectInfo
			 newValue, string message, int objectRecursionLevel)
		{
			if (aoi1 != null && aoi2 != null)
			{
				if (aoi1.GetOid() != null && aoi1.GetOid().Equals(aoi2.GetOid()))
				{
					changedObjectMetaRepresentations.Add(aoi2);
					changes.Add(new ChangedObjectInfo(aoi1
						.GetClassInfo(), aoi2.GetClassInfo(), fieldId, oldValue, newValue, message, objectRecursionLevel
						));
					// also the max recursion level
					if (objectRecursionLevel > maxObjectRecursionLevel)
					{
						maxObjectRecursionLevel = objectRecursionLevel;
					}
					nbChanges++;
				}
				else
				{
					newObjects.Add(aoi2.GetObject());
					string fieldName = aoi1.GetClassInfo().GetAttributeInfoFromId(fieldId).GetName();
					// keep track of the position where the reference must be
					// updated - use aoi1 to get position, because aoi2 do not have position defined yet
					long positionToUpdateReference = aoi1.GetAttributeDefinitionPosition(fieldId);
					StoreNewObjectReference(positionToUpdateReference, aoi2, objectRecursionLevel, fieldName
						);
				}
			}
			else
			{
				//newObjectMetaRepresentations.add(aoi2);
				NeoDatis.Tool.DLogger.Info("Non native object with null object");
			}
		}
		public virtual object BuildOneInstance(NonNativeObjectInfo objectInfo)
		{
			ICache cache = GetSession().GetCache();
			
			// verify if the object is check to delete
			if (objectInfo.IsDeletedObject())
			{
				throw new ODBRuntimeException(NeoDatisError.ObjectIsMarkedAsDeletedForOid.AddParameter(objectInfo.GetOid()));
			}
			// Then check if object is in cache
			object o = cache.GetObjectWithOid(objectInfo.GetOid());
			if (o != null)
			{
				return o;
			}
			Type instanceClazz = null;
			instanceClazz = classPool.GetClass(objectInfo.GetClassInfo().GetFullClassName());
			try
			{
				o = classIntrospector.NewInstanceOf(instanceClazz);
			}
			catch (System.Exception e)
			{
				throw new ODBRuntimeException(NeoDatisError.InstanciationError.AddParameter(objectInfo.GetClassInfo().GetFullClassName()), e);
			}
			// This can happen if ODB can not create the instance
			// TODO Check if returning null is correct
			if (o == null)
			{
				return null;
			}
			// Keep the initial hash code. In some cases, when the class redefines
			// the hash code method
			// Hash code can return wrong values when attributes are not set (when
			// hash code depends on attribute values)
			// Hash codes are used as the key of the map,
			// So at the end of this method, if hash codes are different, object
			// will be removed from the cache and inserted back
			bool hashCodeIsOk = true;
			int initialHashCode = 0;
			try
			{
				initialHashCode = o.GetHashCode();
			}
			catch (System.Exception)
			{
				hashCodeIsOk = false;
			}
			// Adds this incomplete instance in the cache to manage cyclic reference
			if (hashCodeIsOk)
			{
				cache.AddObject(objectInfo.GetOid(), o, objectInfo.GetHeader());
			}
			ClassInfo ci = objectInfo.GetClassInfo();
			IOdbList<FieldInfo> fields = classIntrospector.GetAllFields(ci.GetFullClassName());
			
			FieldInfo field = null;
			AbstractObjectInfo aoi = null;
			object value = null;
			
			for (int i = 0; i < fields.Count; i++)
			{
				field = fields[i];
				// Gets the id of this field
				int attributeId = ci.GetAttributeId(field.Name);
				if (OdbConfiguration.IsDebugEnabled(LogIdDebug))
				{
					DLogger.Debug("getting field with name " + field.Name + ", attribute id is "+ attributeId);
				}
				aoi = objectInfo.GetAttributeValueFromId(attributeId);
				// Check consistency
				// ensureClassCompatibily(field,
				// instanceInfo.getClassInfo().getAttributeinfo(i).getFullClassname());
				if (aoi != null && (!aoi.IsNull()))
				{
					if (aoi.IsNative())
					{
						if (aoi.IsAtomicNativeObject())
						{
							if (aoi.IsNull())
							{
								value = null;
							}
							else
							{
								value = aoi.GetObject();
							}
						}
						if (aoi.IsCollectionObject())
						{
							value = BuildCollectionInstance((CollectionObjectInfo)aoi);
							// Manage a specific case of Set
							/*
							if (typeof(Java.Util.Set).IsAssignableFrom(field.GetType()) && typeof(ICollection).IsAssignableFrom(value.GetType()))
							{
								Java.Util.Set s = new Java.Util.HashSet();
								s.AddAll((System.Collections.ICollection)value);
								value = s;
							}*/
						}
						if (aoi.IsArrayObject())
						{
							value = BuildArrayInstance((ArrayObjectInfo)aoi);
						}
						if (aoi.IsMapObject())
						{
							value = BuildMapInstance((MapObjectInfo)aoi);
						}
						if (aoi.IsEnumObject())
						{
							value = BuildEnumInstance((EnumNativeObjectInfo)aoi, field.FieldType);
						}
					}
					else
					{
						if (aoi.IsNonNativeObject())
						{
							if (aoi.IsDeletedObject())
							{
								if (NeoDatis.Odb.OdbConfiguration.DisplayWarnings())
								{
									IError warning = NeoDatisError.AttributeReferencesADeletedObject
										.AddParameter(objectInfo.GetClassInfo().GetFullClassName())
										.AddParameter(objectInfo.GetOid()).AddParameter(field.Name);
									DLogger.Info(warning.ToString());
								}
								value = null;
							}
							else
							{
								value = BuildOneInstance((NonNativeObjectInfo)aoi);
							}
						}
					}
					if (value != null)
					{
						if (OdbConfiguration.IsDebugEnabled(LogIdDebug))
						{
							DLogger.Debug("Setting field " + field.Name + "(" + field.GetType().FullName + ") to " + value + " / " + value.GetType().FullName);
						}
						try
						{
							field.SetValue(o, value);
						}
						catch (System.Exception e)
						{
							throw new ODBRuntimeException(NeoDatisError.InstanceBuilderWrongObjectContainerType
								.AddParameter(objectInfo.GetClassInfo().GetFullClassName())
								.AddParameter(value.GetType().FullName).AddParameter(field.GetType().FullName), e);
						}
					}
				}
			}
			if (o != null && !OdbClassUtil.GetFullName(o.GetType()).Equals(objectInfo.GetClassInfo().GetFullClassName()))
			{
				new ODBRuntimeException(NeoDatisError.InstanceBuilderWrongObjectType
						.AddParameter(objectInfo.GetClassInfo().GetFullClassName())
						.AddParameter(o.GetType().FullName));
			}
			if (hashCodeIsOk || initialHashCode != o.GetHashCode())
			{
				// Bug (sf bug id=1875544 )detected by glsender
				// This can happen when an object has redefined its own hashcode
				// method and depends on the field values
				// Then, we have to remove object from the cache and re-insert to
				// correct map hash code
				cache.RemoveObjectWithOid(objectInfo.GetOid());
				// re-Adds instance in the cache
				cache.AddObject(objectInfo.GetOid(), o, objectInfo.GetHeader());
			}
			if (triggerManager != null)
			{
				triggerManager.ManageSelectTriggerAfter(objectInfo.GetClassInfo().GetFullClassName
					(), objectInfo, objectInfo.GetOid());
			}
			if (OdbConfiguration.ReconnectObjectsToSession()) {

			   ICrossSessionCache crossSessionCache = CacheFactory.GetCrossSessionCache(engine.GetBaseIdentification().GetIdentification());
			   crossSessionCache.AddObject(o, objectInfo.GetOid());

		   }
			
			return o;
		}