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; }