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); }
public object BuildOneInstance(NonNativeObjectInfo objectInfo, IOdbCache cache) { // verify if the object is check to delete if (objectInfo.IsDeletedObject()) { throw new OdbRuntimeException( NDatabaseError.ObjectIsMarkedAsDeletedForOid.AddParameter(objectInfo.GetOid())); } // Then check if object is in cache var o = cache.GetObject(objectInfo.GetOid()); if (o != null) { return(o); } try { o = FormatterServices.GetUninitializedObject(objectInfo.GetClassInfo().UnderlyingType); } catch (Exception e) { throw new OdbRuntimeException( NDatabaseError.InstanciationError.AddParameter(objectInfo.GetClassInfo().FullClassName), e); } // This can happen if ODB can not create the instance from security reasons if (o == null) { throw new OdbRuntimeException( NDatabaseError.InstanciationError.AddParameter(objectInfo.GetClassInfo().FullClassName)); } // 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 var hashCodeIsOk = true; var initialHashCode = 0; try { initialHashCode = o.GetHashCode(); } catch { hashCodeIsOk = false; } // Adds this incomplete instance in the cache to manage cyclic reference if (hashCodeIsOk) { cache.AddObject(objectInfo.GetOid(), o, objectInfo.GetHeader()); } var classInfo = objectInfo.GetClassInfo(); var fields = ClassIntrospector.GetAllFieldsFrom(classInfo.UnderlyingType); object value = null; foreach (var fieldInfo in fields) { // Gets the id of this field var attributeId = classInfo.GetAttributeId(fieldInfo.Name); if (OdbConfiguration.IsLoggingEnabled()) { DLogger.Debug(string.Concat("InstanceBuilder: ", "getting field with name ", fieldInfo.Name, ", attribute id is ", attributeId.ToString())); } var abstractObjectInfo = objectInfo.GetAttributeValueFromId(attributeId); // Check consistency // ensureClassCompatibily(field, // instanceInfo.getClassInfo().getAttributeinfo(i).getFullClassname()); if (abstractObjectInfo == null || (abstractObjectInfo.IsNull())) { continue; } if (abstractObjectInfo.IsNative()) { if (abstractObjectInfo.IsAtomicNativeObject()) { value = abstractObjectInfo.IsNull() ? null : abstractObjectInfo.GetObject(); } if (abstractObjectInfo.IsArrayObject()) { value = BuildArrayInstance((ArrayObjectInfo)abstractObjectInfo); } if (abstractObjectInfo.IsEnumObject()) { value = BuildEnumInstance((EnumNativeObjectInfo)abstractObjectInfo, fieldInfo.FieldType); } } else { if (abstractObjectInfo.IsNonNativeObject()) { if (abstractObjectInfo.IsDeletedObject()) { if (OdbConfiguration.IsLoggingEnabled()) { var warning = NDatabaseError.AttributeReferencesADeletedObject.AddParameter( objectInfo.GetClassInfo().FullClassName).AddParameter( objectInfo.GetOid()).AddParameter(fieldInfo.Name); DLogger.Warning("InstanceBuilder: " + warning); } value = null; } else { value = BuildOneInstance((NonNativeObjectInfo)abstractObjectInfo); } } } if (value == null) { continue; } if (OdbConfiguration.IsLoggingEnabled()) { DLogger.Debug(String.Format("InstanceBuilder: Setting field {0}({1}) to {2} / {3}", fieldInfo.Name, fieldInfo.GetType().FullName, value, value.GetType().FullName)); } try { fieldInfo.SetValue(o, value); } catch (Exception e) { throw new OdbRuntimeException( NDatabaseError.InstanceBuilderWrongObjectContainerType.AddParameter( objectInfo.GetClassInfo().FullClassName).AddParameter(value.GetType().FullName) .AddParameter(fieldInfo.GetType().FullName), e); } } if (o.GetType() != objectInfo.GetClassInfo().UnderlyingType) { throw new OdbRuntimeException( NDatabaseError.InstanceBuilderWrongObjectType.AddParameter( objectInfo.GetClassInfo().FullClassName).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.RemoveObjectByOid(objectInfo.GetOid()); // re-Adds instance in the cache cache.AddObject(objectInfo.GetOid(), o, objectInfo.GetHeader()); } if (_triggerManager != null) { _triggerManager.ManageSelectTriggerAfter(objectInfo.GetClassInfo().UnderlyingType, o, objectInfo.GetOid()); } return(o); }