private ArrayObjectInfo IntrospectArray(object array, IDictionary <object, NonNativeObjectInfo> alreadyReadObjects, OdbType odbType, IIntrospectionCallback callback) { var length = ((Array)array).GetLength(0); var elementType = array.GetType().GetElementType(); var type = OdbType.GetFromClass(elementType); if (type.IsAtomicNative()) { return(IntropectAtomicNativeArray(array, type)); } var arrayCopy = new object[length]; for (var i = 0; i < length; i++) { var o = ((Array)array).GetValue(i); if (o != null) { var classInfo = GetClassInfo(o.GetType()); var abstractObjectInfo = GetObjectInfo(o, classInfo, true, alreadyReadObjects, callback); arrayCopy[i] = abstractObjectInfo; } else { arrayCopy[i] = NullNativeObjectInfo.GetInstance(); } } return(new ArrayObjectInfo(arrayCopy, odbType, type.Id)); }
/// <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); }
/// <param name="type"> The class to introspect </param> /// <param name="recursive"> If true, goes does the hierarchy to try to analyze all classes </param> /// <param name="classInfoList"> map with class name that are being introspected, to avoid recursive calls </param> private static ClassInfoList InternalIntrospect(Type type, bool recursive, ClassInfoList classInfoList) { if (classInfoList != null) { var existingClassInfo = classInfoList.GetClassInfoBy(type); if (existingClassInfo != null) { return(classInfoList); } } var classInfo = new ClassInfo(type); if (classInfoList == null) { classInfoList = new ClassInfoList(classInfo); } else { classInfoList.AddClassInfo(classInfo); } var fields = GetAllFieldsFrom(type); var attributes = new OdbList <ClassAttributeInfo>(fields.Count); for (var i = 0; i < fields.Count; i++) { var field = fields[i]; ClassInfo classInfoByName; if (OdbType.GetFromClass(field.FieldType).IsNative()) { classInfoByName = null; } else { if (recursive) { classInfoList = InternalIntrospect(field.FieldType, true, classInfoList); classInfoByName = classInfoList.GetClassInfoBy(field.FieldType); } else { classInfoByName = new ClassInfo(field.FieldType); } } attributes.Add(new ClassAttributeInfo((i + 1), field.Name, field.FieldType, OdbClassNameResolver.GetFullName(field.FieldType), classInfoByName)); } classInfo.Attributes = attributes; classInfo.MaxAttributeId = fields.Count; return(classInfoList); }
/// <summary> /// Store an object with the specific id /// </summary> /// <param name="oid"> </param> /// <param name="plainObject"> </param> private OID InternalStore <T>(OID oid, T plainObject) where T : class { if (GetSession().IsRollbacked()) { throw new OdbRuntimeException( NDatabaseError.OdbHasBeenRollbacked.AddParameter(GetBaseIdentification().ToString())); } if (plainObject == null) { throw new OdbRuntimeException(NDatabaseError.OdbCanNotStoreNullObject); } var type = typeof(T); if (OdbType.IsNative(type)) { throw new OdbRuntimeException( NDatabaseError.OdbCanNotStoreNativeObjectDirectly.AddParameter(type.FullName).AddParameter( OdbType.GetFromClass(type).Name).AddParameter(type.FullName)); } // first detects if we must perform an insert or an update // If object is in the cache, we must perform an update, else an insert var cache = GetSession().GetCache(); var cacheOid = cache.IdOfInsertingObject(plainObject); if (cacheOid != null) { return(cacheOid); } // throw new ODBRuntimeException("Inserting meta representation of // an object without the object itself is not yet supported"); var mustUpdate = cache.Contains(plainObject); // The introspection callback is used to execute some specific task (like calling trigger, for example) while introspecting the object var callback = _introspectionCallbackForInsert; if (mustUpdate) { callback = _introspectionCallbackForUpdate; } // Transform the object into an ObjectInfo var nnoi = (NonNativeObjectInfo) _objectIntrospector.GetMetaRepresentation(plainObject, true, null, callback); // During the introspection process, if object is to be updated, then the oid has been set mustUpdate = nnoi.GetOid() != null; return(mustUpdate ? _objectWriter.UpdateNonNativeObjectInfo(nnoi, false) : _objectWriter.InsertNonNativeObject(oid, nnoi, true)); }
public void It_should_extend_class_info_with_new_attribute_info() { Assert.That(_classInfo.Attributes.Count, Is.EqualTo(3)); var attributeInfo = _classInfo.GetAttributeInfoFromName(_fieldName); Assert.That(attributeInfo, Is.Not.Null); Assert.That(attributeInfo.GetName(), Is.EqualTo(_fieldName)); Assert.That(attributeInfo.GetAttributeType(), Is.EqualTo(OdbType.GetFromClass(_fieldType))); }
public virtual void Test3() { var array1 = new[] { 1, 2 }; AssertEquals(OdbType.Array, OdbType.GetFromClass(array1.GetType())); AssertEquals(OdbType.Integer, OdbType.GetFromClass(array1.GetType()).SubType); var array2 = new[] { "1", "2" }; AssertEquals(OdbType.Array, OdbType.GetFromClass(array2.GetType())); AssertEquals(OdbType.String, OdbType.GetFromClass(array2.GetType()).SubType); }
public void Check_type_conversion() { AssertEquals(OdbType.Integer, OdbType.GetFromClass(typeof(int))); AssertEquals(OdbType.Boolean, OdbType.GetFromClass(typeof(bool))); AssertEquals(OdbType.Byte, OdbType.GetFromClass(typeof(byte))); AssertEquals(OdbType.Character, OdbType.GetFromClass(typeof(char))); AssertEquals(OdbType.Double, OdbType.GetFromClass(typeof(double))); AssertEquals(OdbType.Float, OdbType.GetFromClass(typeof(float))); AssertEquals(OdbType.Long, OdbType.GetFromClass(typeof(long))); AssertEquals(OdbType.Short, OdbType.GetFromClass(typeof(short))); AssertEquals(OdbType.String, OdbType.GetFromClass(typeof(string))); AssertEquals(OdbType.Decimal, OdbType.GetFromClass(typeof(Decimal))); }
public ClassInfo GetClassInfo(Type type) { var odbType = OdbType.GetFromClass(type); if (odbType.IsNative() && !odbType.IsEnum()) { return(null); } var metaModel = _session.GetMetaModel(); if (metaModel.ExistClass(type)) { return(metaModel.GetClassInfo(type, true)); } var classInfoList = ClassIntrospector.Introspect(type, true); _session.GetObjectWriter().AddClasses(classInfoList); return(classInfoList.GetMainClassInfo()); }
private static ArrayObjectInfo IntropectAtomicNativeArray(object array, OdbType type) { var length = ((Array)array).GetLength(0); var arrayCopy = new object[length]; for (var i = 0; i < length; i++) { var o = ((Array)array).GetValue(i); if (o != null) { // If object is not null, try to get the exact type var typeId = OdbType.GetFromClass(o.GetType()).Id; var atomicNativeObjectInfo = new AtomicNativeObjectInfo(o, typeId); arrayCopy[i] = atomicNativeObjectInfo; } else { // Else take the declared type arrayCopy[i] = new NullNativeObjectInfo(type.Id); } } return(new ArrayObjectInfo(arrayCopy, OdbType.Array, type.Id)); }
/// <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); }