private IEnumerable <Reference> CreateChildReferences(ReferenceMetadata metadata) { foreach (Reference reference in this.GetPossibleParents(metadata).SelectMany(m => m.ParentReferences.Value)) { if (reference.Other.Metadata.Equals(metadata)) { yield return(reference.Other); } } }
private IEnumerable <ReferenceMetadata> CreateProperties(IMetadataBuilderContext context, ReferenceMetadata parent) { foreach (IRelationMetadata attribute in parent.Relation.Properties) { ReferenceMetadata metadata = this.CreateBaseMetadata(context, attribute, parent); context.AddMetadata <IReferenceMetadata>(metadata); yield return(metadata); } }
private ReferenceMetadata CreateItem(IMetadataBuilderContext context, ReferenceMetadata parent) { if (parent.Relation.Item != null) { ReferenceMetadata metadata = this.CreateBaseMetadata(context, parent.Relation.Item, parent); context.AddMetadata <IReferenceMetadata>(metadata); return(metadata); } return(null); }
private IEnumerable <ReferenceKey> GetPossibleChildKeys(ReferenceMetadata parent) { IEnumerable <ReferenceKey> childKeys = parent.Properties.Value.SelectMany(a => a.Keys.Value); IEnumerable <ReferenceKey> itemKeys = parent.Properties.Value.Where(m => m.Item != null).SelectMany(a => a.Item.Keys.Value); IEnumerable <ReferenceKey> allKeys = childKeys.Concat(itemKeys); if (parent.Relation.HasFlag(RelationMetadataFlags.Recursive)) { allKeys = allKeys.Concat(parent.Keys.Value); } return(allKeys); }
private IEnumerable <ReferenceMetadata> GetPossibleParents(ReferenceMetadata metadata) { if (metadata.Parent != null) { if (!metadata.Parent.HasFlag(RelationMetadataFlags.List)) { yield return(metadata.Parent); } else if (metadata.Parent.Parent != null) { yield return(metadata.Parent.Parent); } } }
private ReferenceMetadata CreateBaseMetadata(IMetadataBuilderContext context, IRelationMetadata relation, ReferenceMetadata parent) { ReferenceMetadata metadata = new ReferenceMetadata(relation) { Parent = parent, }; metadata.Flags = this.CreateFlags(metadata); metadata.Properties = this.CreateLazy(() => this.CreateProperties(context, metadata)); metadata.Keys = this.CreateLazy(() => this.CreateKeys(metadata)); metadata.Item = this.CreateItem(context, metadata); metadata.ParentReferences = this.CreateLazy(() => this.CreateParentReferences(metadata).ToList()); metadata.ChildReferences = this.CreateLazy(() => this.CreateChildReferences(metadata)); return(metadata); }
private bool IsOneType(ReferenceMetadata metadata) { if (!metadata.Type.IsGenericType) { return(false); } Type openType = metadata.Type.GetGenericTypeDefinition(); if (openType == typeof(One <>)) { return(true); } return(false); }
private IEnumerable <ReferenceKey> CreateKeys(ReferenceMetadata parent) { if (this.IsNativeKeylessType(parent.Type)) { return(Array.Empty <ReferenceKey>()); } List <(ReferenceMetadata Metadata, KeyAttribute Attribute, string KeyName)> keyMap = new List <(ReferenceMetadata, KeyAttribute, string)>(); List <(ReferenceMetadata Metadata, RefAttribute Attribute, string ReferenceName, string KeyName)> refMap = new List <(ReferenceMetadata, RefAttribute, string, string)>(); foreach (ReferenceMetadata property in parent.Properties.Value) { foreach (KeyAttribute keyAttr in property.Relation.Annotations.OfType <KeyAttribute>()) { string keyName = keyAttr.Name ?? property.Relation.Member?.Name ?? ""; keyMap.Add((property, keyAttr, keyName)); } foreach (RefAttribute refAttr in property.Relation.Annotations.OfType <RefAttribute>()) { string refName = refAttr.Name; string keyName = refAttr.KeyName ?? property.Relation.Member?.Name ?? ""; refMap.Add((property, refAttr, refName, keyName)); } } IEnumerable <ReferenceKey> candidateKeys = keyMap.GroupBy(t => t.KeyName).Select(g => new ReferenceKey() { Flags = g.All(t => t.Attribute.IsPrimary) ? ReferenceKeyFlags.Primary : ReferenceKeyFlags.Candidate, Name = g.First().KeyName, Properties = g.OrderBy(t => t.Attribute.Index).Select(t => t.Metadata).ToList(), }); IEnumerable <ReferenceKey> foreignKeys = refMap.GroupBy(t => (t.ReferenceName, t.KeyName)).Select(g => new ReferenceKey() { Flags = ReferenceKeyFlags.Foreign, Name = g.First().ReferenceName, Other = g.First().KeyName, Properties = g.OrderBy(t => t.Attribute.Index).Select(t => t.Metadata).ToList(), }); return(candidateKeys.Concat(foreignKeys)); }
private ReferenceMetadataFlags CreateFlags(ReferenceMetadata parent) { ReferenceMetadataFlags flags = ReferenceMetadataFlags.None; if (parent.Relation.Annotations.OfType <KeyAttribute>().Any(k => k.IsPrimary)) { flags |= ReferenceMetadataFlags.PrimaryKey; } else if (parent.Relation.Annotations.OfType <KeyAttribute>().Any()) { flags |= ReferenceMetadataFlags.CandidateKey; } if (parent.Relation.Annotations.OfType <RefAttribute>().Any()) { flags |= ReferenceMetadataFlags.ForeignKey; } return(flags); }
private IEnumerable <Reference> CreateParentReferences(ReferenceMetadata parent) { if (!parent.Keys.Value.Any()) { return(Array.Empty <Reference>()); } IEnumerable <ReferenceKey> parentKeys = parent.Keys.Value; IEnumerable <ReferenceKey> childKeys = this.GetPossibleChildKeys(parent); List <Reference> references = new List <Reference>(); foreach (ReferenceKey parentKey in parentKeys) { foreach (ReferenceKey childKey in childKeys) { if (this.IsKeyMatch(childKey, parentKey)) { ReferenceMetadata childMetadata = childKey.Properties.First().Parent; Reference childRef = new Reference() { Metadata = childMetadata, Flags = ReferenceFlags.Child, Key = childKey, }; Reference parentRef = new Reference() { Metadata = parent, Flags = ReferenceFlags.Parent | ReferenceFlags.One, Key = parentKey, }; if (childKey.HasFlag(ReferenceKeyFlags.Candidate)) { childRef.Flags |= childKey.HasFlag(ReferenceKeyFlags.Primary) ? ReferenceFlags.Primary : ReferenceFlags.Candidate; parentRef.Flags |= ReferenceFlags.Foreign; if (childKey.HasFlag(ReferenceKeyFlags.Primary)) { childRef.Flags |= ReferenceFlags.Primary; } } else { childRef.Flags |= ReferenceFlags.Foreign; parentRef.Flags |= parentKey.HasFlag(ReferenceKeyFlags.Primary) ? ReferenceFlags.Primary : ReferenceFlags.Candidate; } if (childMetadata.Relation.HasFlag(RelationMetadataFlags.Item)) { childRef.List = parentRef.List = childMetadata.Parent; if (this.IsOneType(childMetadata.Parent)) { parentRef.Flags &= ~ReferenceFlags.One; parentRef.Flags |= ReferenceFlags.Many; childRef.Flags |= ReferenceFlags.One; } else { childRef.Flags |= ReferenceFlags.Many; } } else if (this.HasOneAttribute(childMetadata)) { parentRef.Flags &= ~ReferenceFlags.One; parentRef.Flags |= ReferenceFlags.Many; childRef.Flags |= ReferenceFlags.One; } else { childRef.Flags |= ReferenceFlags.One; } if (childMetadata.Equals(parent)) { parentRef.Flags |= ReferenceFlags.Self | ReferenceFlags.Child; childRef.Flags |= ReferenceFlags.Self | ReferenceFlags.Parent; } parentRef.Priority = childRef.Priority = this.GetPriority(parentRef, childRef); parentRef.Other = childRef; childRef.Other = parentRef; references.Add(parentRef); } } } return(references); }
private bool HasOneAttribute(ReferenceMetadata metadata) => metadata.Annotations.OfType <OneAttribute>().Any();