//private static object GetAdjustedColumnValue(DataRow row, string columnName, Func<object, object> transform, PropertyInfo prop)
        private static object GetAdjustedColumnValue(DataRow row, string columnName, object value, PropertyInfo prop)
        {
            if (row == null)
            {
                return(null);
            }

            var column = row.Table.Columns[columnName];

            object val;

            if (prop.PropertyType.IsEnum)
            {
                val = (int)Enum.Parse(prop.PropertyType, value.ToString());
            }
            else if (column.ColumnName == "Id")
            {
                val = HttpDataProvider.GetRemoteRowId(row);
            }
            else
            {
                val = (string.IsNullOrEmpty(value.ToString()))
                                        ? null
                                        : Convert.ChangeType(value, prop.PropertyType);
            }
            return(val);
        }
        internal static void ProcessObjectProperties(object source, DataRow row, IMapping mapping)
        {
            foreach (var parentMapping in mapping.Parents)
            {
                object realSource, value;

                var dataRelation = parentMapping.Value;

                var keyField = (dataRelation.ChildProperty != null) ?
                               dataRelation.PropertyName + "." + dataRelation.ChildProperty :
                               dataRelation.PropertyName;

                try
                {
                    var prop = GetProperty(source, keyField, out realSource);
                    if (dataRelation.RelationName == null)
                    {
                        value = prop.GetValue(realSource, null);
                    }
                    else
                    {
                        if (dataRelation.ParentColumn != "Id")
                        {
                            var parentTable  = row.Table.ParentRelations[dataRelation.RelationName].ParentTable;
                            var parentColumn = parentTable.Columns[dataRelation.ParentColumn];
                            var parentValue  = prop.GetValue(realSource, null);

                            if (parentValue == null)
                            {
                                continue;
                            }

                            var parents = parentTable.Select($"{parentColumn} = '{parentValue}'");

                            var targetRow = (parents.Length > 0) ? parents[0] : parentTable.NewRow();

                            if (dataRelation.ChildType != null)
                            {
                                ProcessSimpleProperties(realSource, targetRow, Topology[dataRelation.ChildType]);
                            }
                            else
                            {
                                targetRow[parentColumn] = parentValue;
                            }

                            if (targetRow.RowState == DataRowState.Detached)
                            {
                                parentTable.Rows.Add(targetRow);
                            }

                            value = targetRow["Id"];
                        }
                        else
                        {
                            if (dataRelation.DownstreamTransform != null)
                            {
                                value = dataRelation.DownstreamTransform(source, row);
                            }
                            else
                            {
                                var parentObject = prop.GetValue(realSource, null);
                                value = (parentObject != null) ? HttpDataProvider.GetLocalRowId((IUniqueId)parentObject) : DBNull.Value;
                            }
                        }
                    }
                }
                catch (Exception ex) {
                    value = DBNull.Value;
                }
                row[parentMapping.Key] = value;
            }
        }
        internal static void ProcessDataRowParents(DataRow row, object target, IMapping mapping)
        {
            foreach (var parentMapping in mapping.Parents)
            {
                object realTarget, value;
                var    prop = GetProperty(target, parentMapping.Value.PropertyName, out realTarget);

                var dataRelation = parentMapping.Value;


                if (dataRelation.RelationName == null)
                {
                    value = dataRelation.UpstreamTransform(dataRelation.ParentColumn, row, target);
                }
                else
                {
                    var parentRow = row.GetParentRow(dataRelation.RelationName);
                    if (parentRow == null)
                    {
                        value = null;
                    }
                    else
                    {
                        if (parentMapping.Value.ChildType == null)
                        {
                            value = dataRelation.UpstreamTransform(dataRelation.ParentColumn, parentRow, target);
                            value = GetAdjustedColumnValue(parentRow, dataRelation.ParentColumn, value, prop);
                        }
                        else
                        {
                            if (parentRow != null)
                            {
                                value = Activator.CreateInstance(dataRelation.ChildType);

                                var cachedMeta = HttpDataProvider.GetHttpMappingByRow(parentRow);
                                if (cachedMeta != null)
                                {
                                    if (value is BaseModel)
                                    {
                                        ((BaseModel)value).UniqueId = cachedMeta.RemoteId;
                                        ((BaseModel)value).ETag     = cachedMeta.ETag;
                                        if (value is BaseModelWithCompanyId)
                                        {
                                            ((BaseModelWithCompanyId)value).CompanyId = cachedMeta.RemoteCompanyId;
                                        }
                                    }
                                    else
                                    {
                                        // maybe the object still wants to map to to a related object
                                        // (e.g. Document.BillTo still refers to a Contact.
                                        var p = value.GetType().GetProperty("UniqueId");
                                        if (p != null)
                                        {
                                            p.SetValue(value, cachedMeta.RemoteId, null);
                                        }
                                    }
                                }

                                DataRowToObject(parentRow, value);
                            }
                            else
                            {
                                value = null;
                            }
                        }
                    }
                }
                prop.SetValue(realTarget, value, null);
            }
        }