Updates referencesource to .NET 4.7
[mono-project.git] / mcs / class / referencesource / System.Data.Entity / System / Data / Mapping / FunctionImportMapping.ReturnTypeRenameMapping.cs
blob18bffc41dc02ebab4fb00ec31c75e5ef50e719b2
1 //---------------------------------------------------------------------
2 // <copyright file="FunctionImportMapping.ReturnTypeRanameMapping.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
4 // </copyright>
5 //
6 // @owner Microsoft
7 // @backupOwner Microsoft
8 //---------------------------------------------------------------------
10 using System;
11 using System.Collections.Generic;
12 using System.Linq;
13 using System.Text;
14 using System.Data.Metadata.Edm;
15 using System.Data.Common.Utils;
16 using System.Xml;
17 using System.Collections.ObjectModel;
18 using System.Diagnostics;
20 namespace System.Data.Mapping
22 internal abstract class FunctionImportStructuralTypeMapping
24 internal readonly LineInfo LineInfo;
25 internal readonly Collection<FunctionImportReturnTypePropertyMapping> ColumnsRenameList;
27 internal FunctionImportStructuralTypeMapping(Collection<FunctionImportReturnTypePropertyMapping> columnsRenameList, LineInfo lineInfo)
29 this.ColumnsRenameList = columnsRenameList;
30 this.LineInfo = lineInfo;
34 internal sealed class FunctionImportEntityTypeMapping : FunctionImportStructuralTypeMapping
36 internal FunctionImportEntityTypeMapping(IEnumerable<EntityType> isOfTypeEntityTypes,
37 IEnumerable<EntityType> entityTypes, IEnumerable<FunctionImportEntityTypeMappingCondition> conditions,
38 Collection<FunctionImportReturnTypePropertyMapping> columnsRenameList,
39 LineInfo lineInfo)
40 : base(columnsRenameList, lineInfo)
42 this.IsOfTypeEntityTypes = new ReadOnlyCollection<EntityType>(
43 EntityUtil.CheckArgumentNull(isOfTypeEntityTypes, "isOfTypeEntityTypes").ToList());
44 this.EntityTypes = new ReadOnlyCollection<EntityType>(
45 EntityUtil.CheckArgumentNull(entityTypes, "entityTypes").ToList());
46 this.Conditions = new ReadOnlyCollection<FunctionImportEntityTypeMappingCondition>(
47 EntityUtil.CheckArgumentNull(conditions, "conditions").ToList());
50 internal readonly ReadOnlyCollection<FunctionImportEntityTypeMappingCondition> Conditions;
51 internal readonly ReadOnlyCollection<EntityType> EntityTypes;
52 internal readonly ReadOnlyCollection<EntityType> IsOfTypeEntityTypes;
54 /// <summary>
55 /// Gets all (concrete) entity types implied by this type mapping.
56 /// </summary>
57 internal IEnumerable<EntityType> GetMappedEntityTypes(ItemCollection itemCollection)
59 const bool includeAbstractTypes = false;
60 return this.EntityTypes.Concat(
61 this.IsOfTypeEntityTypes.SelectMany(entityType =>
62 MetadataHelper.GetTypeAndSubtypesOf(entityType, itemCollection, includeAbstractTypes)
63 .Cast<EntityType>()));
66 internal IEnumerable<String> GetDiscriminatorColumns()
68 return this.Conditions.Select(condition => condition.ColumnName);
72 internal sealed class FunctionImportComplexTypeMapping : FunctionImportStructuralTypeMapping
74 internal readonly ComplexType ReturnType;
76 internal FunctionImportComplexTypeMapping(ComplexType returnType, Collection<FunctionImportReturnTypePropertyMapping> columnsRenameList, LineInfo lineInfo)
77 : base(columnsRenameList, lineInfo)
79 this.ReturnType = returnType;
83 internal abstract class FunctionImportReturnTypePropertyMapping
85 internal readonly string CMember;
86 internal readonly string SColumn;
87 internal readonly LineInfo LineInfo;
89 internal FunctionImportReturnTypePropertyMapping(string cMember, string sColumn, LineInfo lineInfo)
91 this.CMember = cMember;
92 this.SColumn = sColumn;
93 this.LineInfo = lineInfo;
97 internal sealed class FunctionImportReturnTypeScalarPropertyMapping : FunctionImportReturnTypePropertyMapping
99 internal FunctionImportReturnTypeScalarPropertyMapping(string cMember, string sColumn, LineInfo lineInfo)
100 : base(cMember, sColumn, lineInfo)
105 /// <summary>
106 /// extract the column rename info from polymorphic entity type mappings
107 /// </summary>
108 internal sealed class FunctionImportReturnTypeEntityTypeColumnsRenameBuilder
110 /// <summary>
111 /// CMember -> SMember*
112 /// </summary>
113 internal Dictionary<string, FunctionImportReturnTypeStructuralTypeColumnRenameMapping> ColumnRenameMapping;
115 internal FunctionImportReturnTypeEntityTypeColumnsRenameBuilder(
116 Dictionary<EntityType, Collection<FunctionImportReturnTypePropertyMapping>> isOfTypeEntityTypeColumnsRenameMapping,
117 Dictionary<EntityType, Collection<FunctionImportReturnTypePropertyMapping>> entityTypeColumnsRenameMapping)
119 EntityUtil.CheckArgumentNull(isOfTypeEntityTypeColumnsRenameMapping, "isOfTypeEntityTypeColumnsRenameMapping");
120 EntityUtil.CheckArgumentNull(entityTypeColumnsRenameMapping, "entityTypeColumnsRenameMapping");
122 this.ColumnRenameMapping = new Dictionary<string, FunctionImportReturnTypeStructuralTypeColumnRenameMapping>();
124 // Assign the columns renameMapping to the result dictionary.
125 foreach (EntityType entityType in isOfTypeEntityTypeColumnsRenameMapping.Keys)
127 this.SetStructuralTypeColumnsRename(
128 entityType, isOfTypeEntityTypeColumnsRenameMapping[entityType], true/*isTypeOf*/);
131 foreach (EntityType entityType in entityTypeColumnsRenameMapping.Keys)
133 this.SetStructuralTypeColumnsRename(
134 entityType, entityTypeColumnsRenameMapping[entityType], false/*isTypeOf*/);
138 /// <summary>
139 /// Set the column mappings for each defaultMemberName.
140 /// </summary>
141 private void SetStructuralTypeColumnsRename(
142 EntityType entityType,
143 Collection<FunctionImportReturnTypePropertyMapping> columnsRenameMapping,
144 bool isTypeOf)
146 EntityUtil.CheckArgumentNull(entityType, "entityType");
147 EntityUtil.CheckArgumentNull(columnsRenameMapping, "columnsRenameMapping");
149 foreach (var mapping in columnsRenameMapping)
151 if (!this.ColumnRenameMapping.Keys.Contains(mapping.CMember))
153 this.ColumnRenameMapping[mapping.CMember] = new FunctionImportReturnTypeStructuralTypeColumnRenameMapping(mapping.CMember);
155 this.ColumnRenameMapping[mapping.CMember].AddRename(new FunctionImportReturnTypeStructuralTypeColumn(mapping.SColumn, entityType, isTypeOf, mapping.LineInfo));
160 internal sealed class FunctionImportReturnTypeStructuralTypeColumn
162 internal readonly StructuralType Type;
163 internal readonly bool IsTypeOf;
164 internal readonly string ColumnName;
165 internal readonly LineInfo LineInfo;
167 internal FunctionImportReturnTypeStructuralTypeColumn(string columnName, StructuralType type, bool isTypeOf, LineInfo lineInfo)
169 this.ColumnName = columnName;
170 this.IsTypeOf = isTypeOf;
171 this.Type = type;
172 this.LineInfo = lineInfo;
176 internal class FunctionImportReturnTypeStructuralTypeColumnRenameMapping
178 private Collection<FunctionImportReturnTypeStructuralTypeColumn> _columnListForType;
179 private Collection<FunctionImportReturnTypeStructuralTypeColumn> _columnListForIsTypeOfType;
180 /// <summary>
181 /// Null if default mapping is not allowed.
182 /// </summary>
183 private readonly string _defaultMemberName;
184 private Memoizer<StructuralType, FunctionImportReturnTypeStructuralTypeColumn> _renameCache;
186 internal FunctionImportReturnTypeStructuralTypeColumnRenameMapping(string defaultMemberName)
188 this._defaultMemberName = defaultMemberName;
189 this._columnListForType = new Collection<FunctionImportReturnTypeStructuralTypeColumn>();
190 this._columnListForIsTypeOfType = new Collection<FunctionImportReturnTypeStructuralTypeColumn>();
191 this._renameCache = new Memoizer<StructuralType, FunctionImportReturnTypeStructuralTypeColumn>(
192 this.GetRename, EqualityComparer<StructuralType>.Default);
195 /// <summary>
196 /// <see cref="GetRename(EdmType, out IXmlLineInfo)"/> for more info.
197 /// </summary>
198 internal string GetRename(EdmType type)
200 IXmlLineInfo lineInfo;
201 return GetRename(type, out lineInfo);
204 /// <summary>
205 /// A default mapping (property "Foo" maps by convention to column "Foo"), if allowed, has the lowest precedence.
206 /// A mapping for a specific type (EntityType="Bar") takes precedence over a mapping for a hierarchy (EntityType="IsTypeOf(Bar)"))
207 /// If there are two hierarchy mappings, the most specific mapping takes precedence.
208 /// For instance, given the types Base, Derived1 : Base, and Derived2 : Derived1,
209 /// w.r.t. Derived1 "IsTypeOf(Derived1)" takes precedence over "IsTypeOf(Base)" when you ask for the rename of Derived1
210 /// </summary>
211 /// <param name="lineInfo">Empty for default rename mapping.</param>
212 internal string GetRename(EdmType type, out IXmlLineInfo lineInfo)
214 Debug.Assert(type is StructuralType, "we can only rename structural type");
215 EntityUtil.CheckArgumentNull(type, "type");
217 var rename = this._renameCache.Evaluate(type as StructuralType);
218 lineInfo = rename.LineInfo;
219 return rename.ColumnName;
222 private FunctionImportReturnTypeStructuralTypeColumn GetRename(StructuralType typeForRename)
224 FunctionImportReturnTypeStructuralTypeColumn ofTypecolumn = _columnListForType.FirstOrDefault(t => t.Type == typeForRename);
225 if (null != ofTypecolumn)
227 return ofTypecolumn;
230 // if there are duplicate istypeof mapping defined rename for the same column, the last one wins
231 FunctionImportReturnTypeStructuralTypeColumn isOfTypeColumn = _columnListForIsTypeOfType.Where(t => t.Type == typeForRename).LastOrDefault();
233 if (null != isOfTypeColumn)
235 return isOfTypeColumn;
237 else
239 // find out all the tyes that is isparent type of this lookup type
240 IEnumerable<FunctionImportReturnTypeStructuralTypeColumn> nodesInBaseHierachy =
241 _columnListForIsTypeOfType.Where(t => t.Type.IsAssignableFrom(typeForRename));
243 if (nodesInBaseHierachy.Count() == 0)
245 // non of its parent is renamed, so it will take the default one
246 return new FunctionImportReturnTypeStructuralTypeColumn(this._defaultMemberName, typeForRename, false, null);
248 else
250 // we will guarantee that there will be some mapping for us on this column
251 // find out which one is lowest on the link
252 return GetLowestParentInHierachy(nodesInBaseHierachy);
257 private FunctionImportReturnTypeStructuralTypeColumn GetLowestParentInHierachy(IEnumerable<FunctionImportReturnTypeStructuralTypeColumn> nodesInHierachy)
259 FunctionImportReturnTypeStructuralTypeColumn lowestParent = null;
260 foreach (var node in nodesInHierachy)
262 if (lowestParent == null)
264 lowestParent = node;
266 else if (lowestParent.Type.IsAssignableFrom(node.Type))
268 lowestParent = node;
271 Debug.Assert(null != lowestParent, "We should have the lowest parent");
272 return lowestParent;
275 internal void AddRename(FunctionImportReturnTypeStructuralTypeColumn renamedColumn)
277 EntityUtil.CheckArgumentNull(renamedColumn, "renamedColumn");
279 if (!renamedColumn.IsTypeOf)
281 // add to collection if the mapping is for specific type
282 this._columnListForType.Add(renamedColumn);
284 else
286 _columnListForIsTypeOfType.Add(renamedColumn);