/// <summary> /// Builds a class info from a class and an existing class info /// The existing class info is used to make sure that fields with the same name will have the same id /// </summary> /// <param name="fullClassName"> The name of the class to get info </param> /// <param name="existingClassInfo"> </param> /// <returns> A ClassInfo - a meta representation of the class </returns> private static ClassInfo GetClassInfo(String fullClassName, ClassInfo existingClassInfo) { var type = TypeResolutionUtils.ResolveType(fullClassName); var classInfo = new ClassInfo(type); var fields = GetAllFieldsFrom(type); var attributes = new OdbList <ClassAttributeInfo>(fields.Count); var maxAttributeId = existingClassInfo.MaxAttributeId; foreach (var fieldInfo in fields) { // Gets the attribute id from the existing class info var attributeId = existingClassInfo.GetAttributeId(fieldInfo.Name); if (attributeId == -1) { maxAttributeId++; // The attribute with field.getName() does not exist in existing class info // create a new id attributeId = maxAttributeId; } var fieldClassInfo = !OdbType.GetFromClass(fieldInfo.FieldType).IsNative() ? new ClassInfo(fieldInfo.FieldType) : null; attributes.Add(new ClassAttributeInfo(attributeId, fieldInfo.Name, fieldInfo.FieldType, OdbClassNameResolver.GetFullName(fieldInfo.FieldType), fieldClassInfo)); } classInfo.Attributes = attributes; classInfo.MaxAttributeId = maxAttributeId; return(classInfo); }
public int[] GetOrderByAttributeIds(ClassInfo classInfo, IInternalQuery query) { var fieldNames = query.GetOrderByFieldNames(); var fieldIds = new int[fieldNames.Count]; for (var i = 0; i < fieldNames.Count; i++) { fieldIds[i] = classInfo.GetAttributeId(fieldNames[i]); } return(fieldIds); }
/// <summary> /// Transform a list of field names into a list of field ids /// </summary> /// <param name="fields"> </param> /// <returns> The array of field ids </returns> private int[] GetAllInvolvedFieldIds(IList <string> fields) { var nbFields = fields.Count; var fieldIds = new int[nbFields]; for (var i = 0; i < nbFields; i++) { fieldIds[i] = _classInfo.GetAttributeId(fields[i]); } return(fieldIds); }
/// <summary>Builds a class info from a class and an existing class info /// /// <pre> /// The existing class info is used to make sure that fields with the same name will have /// the same id /// </pre> /// /// </summary> /// <param name="fullClassName">The name of the class to get info /// </param> /// <param name="existingClassInfo"> /// </param> /// <returns> A ClassInfo - a meta representation of the class /// </returns> public ClassInfo GetClassInfo(System.String fullClassName, ClassInfo existingClassInfo) { ClassInfo classInfo = new ClassInfo(fullClassName); classInfo.SetClassCategory(GetClassCategory(fullClassName)); ; IOdbList <FieldInfo> fields = GetAllFields(fullClassName); IOdbList <ClassAttributeInfo> attributes = new OdbArrayList <ClassAttributeInfo>(fields.Count); int attributeId = -1; int maxAttributeId = existingClassInfo.GetMaxAttributeId(); ClassInfo ci = null; for (int i = 0; i < fields.Count; i++) { FieldInfo field = fields[i]; // Gets the attribute id from the existing class info attributeId = existingClassInfo.GetAttributeId(field.Name); if (attributeId == -1) { maxAttributeId++; // The attibute with field.getName() does not exist in existing class info // create a new id attributeId = maxAttributeId; } if (!ODBType.GetFromClass(field.FieldType).IsNative()) { ci = new ClassInfo(OdbClassUtil.GetFullName(field.FieldType)); } else { ci = null; } attributes.Add(new ClassAttributeInfo(attributeId, field.Name, field.FieldType, OdbClassUtil.GetFullName(field.FieldType), ci)); } classInfo.SetAttributes(attributes); classInfo.SetMaxAttributeId(maxAttributeId); return(classInfo); }
/// <summary> /// Build a meta representation of an object /// <pre>warning: When an object has two fields with the same name /// (a private field with the same name in a parent class, the deeper field (of the parent) is ignored!)</pre> /// </summary> /// <returns> The ObjectInfo </returns> private AbstractObjectInfo GetObjectInfoInternal(AbstractObjectInfo nnoi, object o, ClassInfo classInfo, bool recursive, IDictionary <object, NonNativeObjectInfo> alreadyReadObjects, IIntrospectionCallback callback) { if (o == null) { return(NullNativeObjectInfo.GetInstance()); } var clazz = o.GetType(); var type = OdbType.GetFromClass(clazz); if (type.IsNative()) { return(GetNativeObjectInfoInternal(type, o, recursive, alreadyReadObjects, callback)); } // sometimes the type.getName() may not match the ci.getClassName() // It happens when the attribute is an interface or superclass of the // real attribute class // In this case, ci must be updated to the real class info if (classInfo != null && !classInfo.FullClassName.Equals(OdbClassNameResolver.GetFullName(clazz))) { classInfo = GetClassInfo(clazz); nnoi = null; } var mainAoi = (NonNativeObjectInfo)nnoi; var isRootObject = false; if (alreadyReadObjects == null) { alreadyReadObjects = new OdbHashMap <object, NonNativeObjectInfo>(); isRootObject = true; } NonNativeObjectInfo cachedNnoi; alreadyReadObjects.TryGetValue(o, out cachedNnoi); if (cachedNnoi != null) { return(new ObjectReference(cachedNnoi)); } if (callback != null) { callback.ObjectFound(o); } if (mainAoi == null) { mainAoi = BuildNnoi(o, classInfo); } alreadyReadObjects[o] = mainAoi; var fields = ClassIntrospector.GetAllFieldsFrom(clazz); foreach (var field in fields) { try { var value = field.GetValue(o); var attributeId = classInfo.GetAttributeId(field.Name); if (attributeId == -1) { throw new OdbRuntimeException( NDatabaseError.ObjectIntrospectorNoFieldWithName.AddParameter(classInfo.FullClassName). AddParameter(field.Name)); } var valueType = OdbType.GetFromClass(value == null ? field.FieldType : value.GetType()); // for native fields AbstractObjectInfo abstractObjectInfo; if (valueType.IsNative()) { abstractObjectInfo = GetNativeObjectInfoInternal(valueType, value, recursive, alreadyReadObjects, callback); mainAoi.SetAttributeValue(attributeId, abstractObjectInfo); } else { // Non Native Objects if (value == null) { var classInfo1 = GetClassInfo(field.GetType()); abstractObjectInfo = new NonNativeNullObjectInfo(classInfo1); mainAoi.SetAttributeValue(attributeId, abstractObjectInfo); } else { var classInfo2 = GetClassInfo(value.GetType()); if (recursive) { abstractObjectInfo = GetObjectInfoInternal(null, value, classInfo2, true, alreadyReadObjects, callback); mainAoi.SetAttributeValue(attributeId, abstractObjectInfo); } else { // When it is not recursive, simply add the object // values.add(value); throw new OdbRuntimeException( NDatabaseError.InternalError.AddParameter( "Should not enter here - ObjectIntrospector - 'simply add the object'")); } } } } catch (ArgumentException e) { throw new OdbRuntimeException( NDatabaseError.InternalError.AddParameter("in getObjectInfoInternal"), e); } catch (MemberAccessException e) { throw new OdbRuntimeException(NDatabaseError.InternalError.AddParameter("getObjectInfoInternal"), e); } } if (isRootObject) { alreadyReadObjects.Clear(); } return(mainAoi); }
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); }
/// <summary> /// Builds a class info from a class and an existing class info /// The existing class info is used to make sure that fields with the same name will have the same id /// </summary> /// <param name="fullClassName"> The name of the class to get info </param> /// <param name="existingClassInfo"> </param> /// <returns> A ClassInfo - a meta representation of the class </returns> private static ClassInfo GetClassInfo(String fullClassName, ClassInfo existingClassInfo) { var type = TypeResolutionUtils.ResolveType(fullClassName); var classInfo = new ClassInfo(type); var fields = GetAllFieldsFrom(type); var attributes = new OdbList<ClassAttributeInfo>(fields.Count); var maxAttributeId = existingClassInfo.MaxAttributeId; foreach (var fieldInfo in fields) { // Gets the attribute id from the existing class info var attributeId = existingClassInfo.GetAttributeId(fieldInfo.Name); if (attributeId == - 1) { maxAttributeId++; // The attribute with field.getName() does not exist in existing class info // create a new id attributeId = maxAttributeId; } var fieldClassInfo = !OdbType.GetFromClass(fieldInfo.FieldType).IsNative() ? new ClassInfo(fieldInfo.FieldType) : null; attributes.Add(new ClassAttributeInfo(attributeId, fieldInfo.Name, fieldInfo.FieldType, OdbClassNameResolver.GetFullName(fieldInfo.FieldType), fieldClassInfo)); } classInfo.Attributes = attributes; classInfo.MaxAttributeId = maxAttributeId; return classInfo; }
/// <summary> /// Build a meta representation of an object /// <pre>warning: When an object has two fields with the same name /// (a private field with the same name in a parent class, the deeper field (of the parent) is ignored!)</pre> /// </summary> /// <returns> The ObjectInfo </returns> private AbstractObjectInfo GetObjectInfoInternal(AbstractObjectInfo nnoi, object o, ClassInfo classInfo, bool recursive, IDictionary<object, NonNativeObjectInfo> alreadyReadObjects, IIntrospectionCallback callback) { if (o == null) return NullNativeObjectInfo.GetInstance(); var clazz = o.GetType(); var type = OdbType.GetFromClass(clazz); if (type.IsNative()) return GetNativeObjectInfoInternal(type, o, recursive, alreadyReadObjects, callback); // sometimes the type.getName() may not match the ci.getClassName() // It happens when the attribute is an interface or superclass of the // real attribute class // In this case, ci must be updated to the real class info if (classInfo != null && !classInfo.FullClassName.Equals(OdbClassNameResolver.GetFullName(clazz))) { classInfo = GetClassInfo(clazz); nnoi = null; } var mainAoi = (NonNativeObjectInfo) nnoi; var isRootObject = false; if (alreadyReadObjects == null) { alreadyReadObjects = new OdbHashMap<object, NonNativeObjectInfo>(); isRootObject = true; } NonNativeObjectInfo cachedNnoi; alreadyReadObjects.TryGetValue(o, out cachedNnoi); if (cachedNnoi != null) return new ObjectReference(cachedNnoi); if (callback != null) callback.ObjectFound(o); if (mainAoi == null) mainAoi = BuildNnoi(o, classInfo); alreadyReadObjects[o] = mainAoi; var fields = ClassIntrospector.GetAllFieldsFrom(clazz); foreach (var field in fields) { try { var value = field.GetValue(o); var attributeId = classInfo.GetAttributeId(field.Name); if (attributeId == -1) { throw new OdbRuntimeException( NDatabaseError.ObjectIntrospectorNoFieldWithName.AddParameter(classInfo.FullClassName). AddParameter(field.Name)); } var valueType = OdbType.GetFromClass(value == null ? field.FieldType : value.GetType()); // for native fields AbstractObjectInfo abstractObjectInfo; if (valueType.IsNative()) { abstractObjectInfo = GetNativeObjectInfoInternal(valueType, value, recursive, alreadyReadObjects, callback); mainAoi.SetAttributeValue(attributeId, abstractObjectInfo); } else { // Non Native Objects if (value == null) { var classInfo1 = GetClassInfo(field.GetType()); abstractObjectInfo = new NonNativeNullObjectInfo(classInfo1); mainAoi.SetAttributeValue(attributeId, abstractObjectInfo); } else { var classInfo2 = GetClassInfo(value.GetType()); if (recursive) { abstractObjectInfo = GetObjectInfoInternal(null, value, classInfo2, true, alreadyReadObjects, callback); mainAoi.SetAttributeValue(attributeId, abstractObjectInfo); } else { // When it is not recursive, simply add the object // values.add(value); throw new OdbRuntimeException( NDatabaseError.InternalError.AddParameter( "Should not enter here - ObjectIntrospector - 'simply add the object'")); } } } } catch (ArgumentException e) { throw new OdbRuntimeException( NDatabaseError.InternalError.AddParameter("in getObjectInfoInternal"), e); } catch (MemberAccessException e) { throw new OdbRuntimeException(NDatabaseError.InternalError.AddParameter("getObjectInfoInternal"), e); } } if (isRootObject) alreadyReadObjects.Clear(); return mainAoi; }