/// <summary>
        /// This method is responsible for translanting between coded domain names
        /// and their values, setting into UnderlyingObject the correct value.
        /// </summary>
        /// <remarks>
        /// Imagine a ICodedDomain like:
        /// 1 = "Alphanumeric"
        /// 2 = "Geographic"
        /// 
        /// This method will aways set the value to 1 when passed
        /// "Alphanumeric"
        /// </remarks>
        /// <exception cref="ActiveRecrdAttributeException"></exception>
        /// <param name="wrapper"></param>
        /// <param name="propertyName"></param>
        /// <param name="displayValue"></param>
        /// <returns></returns>
        private static void SetDisplayValue(this IActiveRecord wrapper, FieldAttribute fieldAtt, string displayValue)
        {
            if (wrapper.UnderlyingObject == null)
                FetchUnderlyingObject(wrapper);

            if (!(fieldAtt is DomainFieldAttribute))
                throw new ActiveRecordAttributeException(wrapper.GetType(), "O atributo não é tipo domínio.");

            DomainFieldAttribute domainField = fieldAtt as DomainFieldAttribute;
            ICodedValueDomain domain = wrapper.UnderlyingObject.Fields.get_Field(domainField.Index).Domain as ICodedValueDomain;

            if (domain == null)
                throw new ActiveRecordAttributeException(wrapper.GetType(), "Não foi possível localizar o domínio.");

            for (var i = 0; i <= domain.CodeCount - 1; i++)
            {
                if (domain.get_Name(i) == displayValue)
                {
                    object codedValue = domain.get_Value(i);
                    wrapper.UnderlyingObject.set_Value(domainField.Index, codedValue);
                }
            }
        }
        /// <summary>
        /// This method is responsible for translating between coded domain values
        /// and their names, returning the correct name.
        /// </summary>
        /// Imagine a ICodedDomain like:
        /// 1 = "Alphanumeric"
        /// 2 = "Geographic"
        /// 
        /// This method will always return "Alphanumeric" for the value 1,
        /// fetched from UnderlyingObject
        /// </remarks>
        /// <exception cref="ActiveRecrdAttributeException"></exception>
        /// <param name="wrapper">IActiveRecord</param>
        /// <param name="propertyName">string</param>
        /// <returns>string</returns>
        private static string GetDisplayValue(this IActiveRecord wrapper, FieldAttribute fieldAtt)
        {
            if (wrapper.UnderlyingObject == null)
                FetchUnderlyingObject(wrapper);

            if (!(fieldAtt is DomainFieldAttribute))
                throw new ActiveRecordAttributeException(wrapper.GetType(), "Não é possível obter o atributo de domínio.");

            DomainFieldAttribute domainField = fieldAtt as DomainFieldAttribute;
            ICodedValueDomain domain = wrapper.UnderlyingObject.Fields.get_Field(domainField.Index).Domain as ICodedValueDomain;

            if (domain == null)
                throw new ActiveRecordAttributeException(wrapper.GetType(),
                    String.Format("Não foi possível localizar o domínio {0}.", domainField.DomainName));

            string codedValue = wrapper.UnderlyingObject.get_Value(domainField.Index).ToString();
            string displayValue = String.Empty;

            for (int i = 0; i <= domain.CodeCount - 1; i++)
            {
                if (domain.get_Value(i).ToString() == codedValue)
                {
                    displayValue = domain.get_Name(i);
                    break;
                }
            }

            if (displayValue == String.Empty)
                return codedValue;
            else
                return displayValue;
        }
        /// <summary>
        /// Gets the other right side of the relationship
        /// </summary>
        /// <param name="wrapper">IActiveRecord</param>
        /// <param name="fieldAttribute">FieldAttribute</param>
        /// <returns>object</returns>
        private static object OneToOne(this IActiveRecord wrapper, FieldAttribute relationshipAttribute)
        {
            if (!(relationshipAttribute is RelationshipAttribute))
                throw new ActiveRecordAttributeException(wrapper.GetType(),
                    "O atributo não é do tipo HasMany. Não foi possível retornar os objetos relacionados.");

            RelationshipAttribute hasMany = relationshipAttribute as RelationshipAttribute;

            object[] customAttributes = hasMany.ClassType.GetCustomAttributes(typeof(RepositoryAttribute), true);
            if (customAttributes.Length != 1)
                throw new ActiveRecordAttributeException(hasMany.ClassType, "Não foi possível encontrar o controlador da classe.");

            RepositoryAttribute controlled = (RepositoryAttribute)customAttributes[0];
            object relatedController = Activator.CreateInstance(controlled.ControllerType);

            if (relatedController == null)
                throw new ActiveRecordAttributeException(controlled.ControllerType, "Não foi possível instanciar o controller.");

            PrimaryFieldAttribute pkAtt = wrapper.GetPrimaryKeyDefinition();
            if (pkAtt == null)
                throw new ActiveRecordAttributeException(wrapper.GetType(), "Não foi possível encontrar a chave primária da classe.");

            IQueryFilter filter = new QueryFilterClass();

            filter.WhereClause = String.Format(pkAtt.QuoteValue ? "{0} = '{1}'" : "{0} = {1}", hasMany.FieldName, wrapper.UnderlyingObject.get_Value(pkAtt.Index));

            // prepare the method for invoke
            // check if the method is lazy or not
            MethodInfo singleMethod = null;
            singleMethod = controlled.ControllerType.GetMethod(hasMany.Lazy ? "Filter" : "FilterLazy");

            var parameters = new object[1];
            parameters[0] = filter;

            // invoke and return
            return singleMethod.Invoke(relatedController, parameters);
        }
        private static object FindRelatedObjects(this IActiveRecord wrapper, FieldAttribute relationshipAttribute)
        {
            List<IActiveRecord> result;

            if (!(relationshipAttribute is RelationshipAttribute))
                throw new ActiveRecordAttributeException(wrapper.GetType(),
                    "O atributo não é do tipo HasMany. Não foi possível retornar os objetos relacionados.");

            var attribute = relationshipAttribute as RelationshipAttribute;

            if (attribute.GetType() == typeof(HasManyAttribute))
                return HasMany(wrapper, relationshipAttribute);

            if (attribute.GetType() == typeof(OneToOneAttribute))
                return OneToOne(wrapper, relationshipAttribute);

            if (attribute.GetType() == typeof(BelongsToAttribute))
                return Belongs(wrapper, relationshipAttribute);

            throw new ActiveRecordAttributeException(wrapper.GetType(), "Não foi possível buscar os objetos relacionados.");
        }
        /// <summary>
        /// Gets the Owner of a specific IActiveRecord
        /// </summary>
        /// <param name="wrapper">IActiveRecord</param>
        /// <param name="propertyName">string</param>
        /// <returns>object</returns>
        private static object Belongs(this IActiveRecord wrapper, FieldAttribute relationshipAttribute)
        {
            if (!(relationshipAttribute is RelationshipAttribute))
                throw new ActiveRecordAttributeException(wrapper.GetType(),
                    "O atributo não é do tipo HasMany. Não foi possível retornar os objetos relacionados.");

            var attribute = relationshipAttribute as BelongsToAttribute;

            object[] customAttributes = attribute.ClassType.GetCustomAttributes(typeof(RepositoryAttribute), true);
            if (customAttributes.Length != 1)
                throw new ActiveRecordAttributeException(attribute.ClassType, "Não foi possível encontrar o controlador da classe.");

            RepositoryAttribute controlled = (RepositoryAttribute)customAttributes[0];
            object relatedController = Activator.CreateInstance(controlled.ControllerType);

            if (relatedController == null)
                throw new ActiveRecordAttributeException(controlled.ControllerType, "Não foi possível instanciar o controller.");

            IQueryFilter filter = new QueryFilterClass();
            filter.WhereClause = String.Format(attribute.QuoteValue ? "{0} = '{1}'" : "{0} = {1}", attribute.FieldName, wrapper.UnderlyingObject.get_Value(attribute.ParentValueFieldIndex));

            // prepare the method for invoke
            // check if the method is lazy or not
            MethodInfo singleMethod = null;
            singleMethod = controlled.ControllerType.GetMethod("SingleByPrimaryKey");

            var parameters = new object[1];
            parameters[0] = wrapper.UnderlyingObject.get_Value(attribute.ParentValueFieldIndex);
            //case not exist value in foreign key, return null
            if (parameters[0] == null || parameters[0].ToString().Equals(""))
                return null;

            // invoke and return
            return singleMethod.Invoke(relatedController, parameters);
        }
 public static void SetCascadingValue(this IActiveRecord wrapper, FieldAttribute fieldAtt, object value)
 {
     throw new NotImplementedException();
 }
        public static void SetBlobValue(this IActiveRecord wrapper, FieldAttribute attribute, object value)
        {
            if (!(value is IPersistStream))
                throw new ActiveRecordException("Nâo é possível persistir um objeto que não implementa IPersistStream.");

            IMemoryBlobStream memStream = new MemoryBlobStreamClass();
            IObjectStream objStream = new ObjectStreamClass();
            objStream.Stream = memStream;
            IPersistStream persist = (IPersistStream)value;
            persist.Save(memStream, 0);

            wrapper.UnderlyingObject.set_Value(attribute.Index, memStream);
        }
        public static object GetBlobValue(this IActiveRecord wrapper, FieldAttribute attribute)
        {
            IMemoryBlobStream blobStream = wrapper.UnderlyingObject.get_Value(attribute.Index) as IMemoryBlobStream;

            if (blobStream == null)
                return null;

            IObjectStream stream = new ObjectStreamClass() { Stream = blobStream };

            IPersistStream blob = new PropertySetClass();
            blob.Load(blobStream);

            return blob as IPropertySet;
        }