Esempio n. 1
0
        public bool ActivateFor(IRow row)
        {
            var attrs = row.GetType().GetCustomAttributes <UpdatableExtensionAttribute>();

            if (attrs == null || !attrs.Any())
            {
                return(false);
            }

            var sourceByExpression = row.GetFields().ToLookup(x =>
                                                              BracketLocator.ReplaceBrackets(x.Expression.TrimToEmpty(), BracketRemoverDialect.Instance));

            infoList = attrs.Select(attr =>
            {
                var info = new RelationInfo
                {
                    Attr = attr
                };

                var rowType = attr.RowType;
                if (rowType.IsAbstract ||
                    !typeof(IRow).IsAssignableFrom(rowType) ||
                    rowType.IsInterface)
                {
                    throw new ArgumentException(string.Format(
                                                    "Row type '{1}' has an ExtensionRelation attribute " +
                                                    "but its specified extension row type '{0}' is not a valid row class!",
                                                    rowType.FullName,
                                                    row.GetType().FullName));
                }

                info.RowFactory = () => (IRow)Activator.CreateInstance(rowType);

                var thisKey = attr.ThisKey;
                if (string.IsNullOrEmpty(thisKey))
                {
                    if (!(row is IIdRow))
                    {
                        throw new ArgumentException(string.Format(
                                                        "Row type '{0}' has an ExtensionRelation attribute " +
                                                        "but its ThisKey is not specified!",
                                                        row.GetType().FullName));
                    }

                    info.ThisKeyField = row.IdField;
                }
                else
                {
                    info.ThisKeyField = row.FindFieldByPropertyName(attr.ThisKey) ??
                                        row.FindField(attr.ThisKey);
                    if (info.ThisKeyField is null)
                    {
                        throw new ArgumentException(string.Format("Field '{0}' doesn't exist in row of type '{1}'." +
                                                                  "This field is specified for an ExtensionRelation attribute",
                                                                  attr.ThisKey,
                                                                  row.GetType().FullName));
                    }
                }

                var ext = info.RowFactory();

                var otherKey = attr.OtherKey;
                if (string.IsNullOrEmpty(otherKey))
                {
                    info.OtherKeyField = ext.FindField(info.ThisKeyField.Name);

                    if (info.OtherKeyField is null && ext is IIdRow)
                    {
                        info.OtherKeyField = row.IdField;
                    }

                    if (info.OtherKeyField is null)
                    {
                        throw new ArgumentException(string.Format(
                                                        "Row type '{1}' has an ExtensionRelation attribute " +
                                                        "but its OtherKey is not specified!",
                                                        row.GetType().FullName));
                    }
                }
                else
                {
                    info.OtherKeyField = ext.FindFieldByPropertyName(attr.OtherKey) ?? ext.FindField(attr.OtherKey);
                    if (info.OtherKeyField is null)
                    {
                        throw new ArgumentException(string.Format("Field '{0}' doesn't exist in row of type '{1}'." +
                                                                  "This field is specified for an ExtensionRelation attribute on '{2}'",
                                                                  attr.OtherKey,
                                                                  ext.GetType().FullName,
                                                                  row.GetType().FullName));
                    }
                }

                if (!string.IsNullOrEmpty(attr.FilterField))
                {
                    info.FilterField = ext.FindFieldByPropertyName(attr.FilterField) ?? ext.FindField(attr.FilterField);
                    if (info.FilterField is null)
                    {
                        throw new ArgumentException(string.Format("Field '{0}' doesn't exist in row of type '{1}'." +
                                                                  "This field is specified as FilterField for an ExtensionRelation attribute on '{2}'",
                                                                  attr.OtherKey,
                                                                  ext.GetType().FullName,
                                                                  row.GetType().FullName));
                    }

                    info.FilterValue = info.FilterField.ConvertValue(attr.FilterValue, CultureInfo.InvariantCulture);
                }

                if (!string.IsNullOrEmpty(attr.PresenceField))
                {
                    info.PresenceField = row.FindFieldByPropertyName(attr.PresenceField) ?? row.FindField(attr.PresenceField);
                    if (info.PresenceField is null)
                    {
                        throw new ArgumentException(string.Format("Field '{0}' doesn't exist in row of type '{1}'." +
                                                                  "This field is specified as PresenceField as an ExtensionRelation attribute.",
                                                                  attr.PresenceField,
                                                                  row.GetType().FullName));
                    }

                    info.PresenceValue = attr.PresenceValue;
                }

                var extFields   = ext.GetFields();
                var alias       = attr.Alias;
                var aliasPrefix = attr.Alias + "_";

                var joinByKey = new HashSet <string>(extFields.Joins.Keys, StringComparer.OrdinalIgnoreCase);

                string mapAlias(string x)
                {
                    if (x == "t0" || x == "T0")
                    {
                        return(alias);
                    }

                    if (!joinByKey.Contains(x))
                    {
                        return(x);
                    }

                    return(aliasPrefix + x);
                }

                string mapExpression(string x)
                {
                    if (x == null)
                    {
                        return(null);
                    }

                    return(JoinAliasLocator.ReplaceAliases(x, mapAlias));
                }

                info.Mappings = new List <Tuple <Field, Field> >();
                foreach (var field in extFields)
                {
                    if (ReferenceEquals(info.OtherKeyField, field))
                    {
                        continue;
                    }

                    if (ReferenceEquals(info.FilterField, field))
                    {
                        continue;
                    }

                    var expression = field.Expression.TrimToEmpty();

                    if (string.IsNullOrEmpty(expression))
                    {
                        continue;
                    }

                    expression = mapExpression(expression);
                    expression = BracketLocator.ReplaceBrackets(expression,
                                                                BracketRemoverDialect.Instance);

                    var match = sourceByExpression[expression].FirstOrDefault();
                    if (match is null)
                    {
                        continue;
                    }

                    if (match.IsTableField())
                    {
                        continue;
                    }

                    if (ReferenceEquals(info.ThisKeyField, match))
                    {
                        continue;
                    }

                    if (field.GetType() != match.GetType())
                    {
                        throw new ArgumentException(string.Format(
                                                        "Row type '{0}' has an ExtensionRelation attribute to '{1}'." +
                                                        "Their '{2}' and '{3}' fields are matched but they have different types ({4} and {5})!",
                                                        row.GetType().FullName,
                                                        ext.GetType().FullName,
                                                        field.PropertyName ?? field.Name,
                                                        match.PropertyName ?? match.Name,
                                                        field.GetType().Name,
                                                        match.GetType().Name));
                    }

                    info.Mappings.Add(new Tuple <Field, Field>(match, field));
                }

                if (info.Mappings.Count == 0)
                {
                    throw new ArgumentException(string.Format(
                                                    "Row type '{0}' has an ExtensionRelation attribute " +
                                                    "but no view fields could be matched to extension row '{1}'!",
                                                    row.GetType().FullName,
                                                    ext.GetType().FullName));
                }

                return(info);
            }).ToList();

            return(true);
        }
        public void ReplaceAliasesIgnoresBracedAliases()
        {
            var result = JoinAliasLocator.ReplaceAliases("x.y + [a].b + y.z + [a].[b].d", x => "_" + x);

            Assert.Equal("_x.y + [a].b + _y.z + [a].[b].d", result);
        }