Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System.Data.Entity / System / Data / Mapping / StorageMappingFragment.cs
1 //---------------------------------------------------------------------
2 // <copyright file="StorageMappingFragment.cs" company="Microsoft">
3 //      Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //
6 // @owner       Microsoft
7 // @backupOwner Microsoft
8 //---------------------------------------------------------------------
9
10 using System;
11 using System.Collections.Generic;
12 using System.Linq;
13 using System.Collections.ObjectModel;
14 using System.Text;
15 using System.Data.Metadata.Edm;
16 using System.Diagnostics;
17
18 namespace System.Data.Mapping {
19     /// <summary>
20     /// Represents the metadata for mapping fragment.
21     /// A set of mapping fragments makes up the Set mappings( EntitySet, AssociationSet or CompositionSet )
22     /// Each MappingFragment provides mapping for those properties of a type that map to a single table.
23     /// </summary>
24     /// <example>
25     /// For Example if conceptually you could represent the CS MSL file as following
26     /// --Mapping
27     ///   --EntityContainerMapping ( CNorthwind-->SNorthwind )
28     ///     --EntitySetMapping
29     ///       --EntityTypeMapping
30     ///         --MappingFragment
31     ///           --EntityKey
32     ///             --ScalarPropertyMap ( CMemberMetadata-->SMemberMetadata )
33     ///           --ScalarPropertyMap ( CMemberMetadata-->SMemberMetadata )
34     ///       --EntityTypeMapping
35     ///         --MappingFragment
36     ///           --EntityKey
37     ///             --ScalarPropertyMap ( CMemberMetadata-->SMemberMetadata )
38     ///           --ComplexPropertyMap
39     ///             --ComplexTypeMapping
40     ///               --ScalarPropertyMap ( CMemberMetadata-->SMemberMetadata )
41     ///               --ScalarProperyMap ( CMemberMetadata-->SMemberMetadata )
42     ///               --DiscriminatorProperyMap ( constant value-->SMemberMetadata )
43     ///             --ComplexTypeMapping
44     ///               --ScalarPropertyMap ( CMemberMetadata-->SMemberMetadata )
45     ///               --ScalarProperyMap ( CMemberMetadata-->SMemberMetadata )
46     ///               --DiscriminatorProperyMap ( constant value-->SMemberMetadata )
47     ///           --ScalarPropertyMap ( CMemberMetadata-->SMemberMetadata )
48     ///     --AssociationSetMapping 
49     ///       --AssociationTypeMapping
50     ///         --MappingFragment
51     ///           --EndPropertyMap
52     ///             --ScalarPropertyMap ( CMemberMetadata-->SMemberMetadata )
53     ///             --ScalarProperyMap ( CMemberMetadata-->SMemberMetadata )
54     ///           --EndPropertyMap
55     ///             --ScalarPropertyMap ( CMemberMetadata-->SMemberMetadata )
56     /// This class represents the metadata for all the mapping fragment elements in the 
57     /// above example. Users can access all the top level constructs of 
58     /// MappingFragment element like EntityKey map, Property Maps, Discriminator
59     /// property through this mapping fragment class.
60     /// </example>
61     internal class StorageMappingFragment {
62         #region Constructors
63         /// <summary>
64         /// Construct a new Mapping Fragment object
65         /// </summary>
66         /// <param name="tableExtent"></param>
67         /// <param name="typeMapping"></param>
68         internal StorageMappingFragment(EntitySet tableExtent, StorageTypeMapping typeMapping, bool distinctFlag) {
69             Debug.Assert(tableExtent != null, "Table should not be null when constructing a Mapping Fragment");
70             Debug.Assert(typeMapping != null, "TypeMapping should not be null when constructing a Mapping Fragment");
71             this.m_tableExtent = tableExtent;
72             this.m_typeMapping = typeMapping;
73             this.m_isSQueryDistinct = distinctFlag;
74         }
75         #endregion
76
77         #region Fields
78         /// <summary>
79         /// Table extent from which the properties are mapped under this fragment.
80         /// </summary>
81         EntitySet m_tableExtent;
82         /// <summary>
83         /// Type mapping under which this mapping fragment exists.
84         /// </summary>
85         StorageTypeMapping m_typeMapping;
86         /// <summary>
87         /// Condition property mappings for this mapping fragment.
88         /// </summary>
89         Dictionary<EdmProperty, StoragePropertyMapping> m_conditionProperties = new Dictionary<EdmProperty, StoragePropertyMapping>(EqualityComparer<EdmProperty>.Default);
90         /// <summary>
91         /// All the other properties .
92         /// </summary>
93         List<StoragePropertyMapping> m_properties = new List<StoragePropertyMapping>();
94         /// <summary>
95         /// Line Number for MappingFragment element start tag.
96         /// </summary>
97         int m_startLineNumber;
98         /// <summary>
99         /// Line position for MappingFragment element start tag.
100         /// </summary>
101         int m_startLinePosition;
102         bool m_isSQueryDistinct;
103         #endregion
104
105         #region Properties
106         /// <summary>
107         /// The table from which the properties are mapped in this fragment
108         /// </summary>
109         internal EntitySet TableSet {
110             get {
111                 return this.m_tableExtent;
112             }
113         }
114
115         internal bool IsSQueryDistinct
116         {
117             get { return m_isSQueryDistinct; }
118         }
119
120         /// <summary>
121         /// Returns all the property mappings defined in the complex type mapping
122         /// including Properties and Condition Properties
123         /// </summary>
124         internal ReadOnlyCollection<StoragePropertyMapping> AllProperties
125         {
126             get
127             {
128                 List<StoragePropertyMapping> properties = new List<StoragePropertyMapping>();
129                 properties.AddRange(m_properties);
130                 properties.AddRange(m_conditionProperties.Values);
131                 return properties.AsReadOnly();
132             }
133         }
134
135         /// <summary>
136         /// Returns all the property mappings defined in the complex type mapping
137         /// including Properties and Condition Properties
138         /// </summary>
139         internal ReadOnlyCollection<StoragePropertyMapping> Properties
140         {
141             get
142             {
143                 return m_properties.AsReadOnly();
144             }
145         }
146         
147         /// <summary>
148         /// Line Number in MSL file where the Mapping Fragment Element's Start Tag is present.
149         /// </summary>
150         internal int StartLineNumber {
151             get {
152                 return m_startLineNumber;
153             }
154             set {
155                 m_startLineNumber = value;
156             }
157         }
158
159         /// <summary>
160         /// Line Position in MSL file where the Mapping Fragment Element's Start Tag is present.
161         /// </summary>
162         internal int StartLinePosition {
163             get {
164                 return m_startLinePosition;
165             }
166             set {
167                 m_startLinePosition = value;
168             }
169         }
170
171         /// <summary>
172         /// File URI of the MSL file
173         /// </summary>
174         //This should not be stored on the Fragment. Probably it should go on schema.
175         //But this requires some thinking before we can finally decide where it should go.
176         internal string SourceLocation {
177             get {
178                 return this.m_typeMapping.SetMapping.EntityContainerMapping.SourceLocation;
179             }
180         }        
181         #endregion
182
183         #region Methods
184         /// <summary>
185         /// Add a property mapping as a child of this mapping fragment
186         /// </summary>
187         /// <param name="prop">child property mapping to be added</param>
188         internal void AddProperty(StoragePropertyMapping prop)
189         {
190             this.m_properties.Add(prop);
191         }
192
193         /// <summary>
194         /// Add a condition property mapping as a child of this complex property mapping
195         /// Condition Property Mapping specifies a Condition either on the C side property or S side property.
196         /// </summary>
197         /// <param name="conditionPropertyMap">The mapping that needs to be added</param>
198         internal void AddConditionProperty(StorageConditionPropertyMapping conditionPropertyMap, Action<EdmMember> duplicateMemberConditionError)
199         {
200             //Same Member can not have more than one Condition with in the 
201             //same Mapping Fragment.
202             EdmProperty conditionMember = (conditionPropertyMap.EdmProperty != null) ? conditionPropertyMap.EdmProperty : conditionPropertyMap.ColumnProperty;
203             Debug.Assert(conditionMember != null);
204             if (!m_conditionProperties.ContainsKey(conditionMember))
205             {
206                 m_conditionProperties.Add(conditionMember, conditionPropertyMap);
207             }
208             else
209             {
210                 duplicateMemberConditionError(conditionMember);
211             }
212         }
213
214         /// <summary>
215         /// This method is primarily for debugging purposes.
216         /// Will be removed shortly.
217         /// </summary>
218         /// <param name="index"></param>
219         internal virtual void Print(int index) {
220             StorageEntityContainerMapping.GetPrettyPrintString(ref index);
221             StringBuilder sb = new StringBuilder();
222             sb.Append("MappingFragment");
223             sb.Append("   ");
224             sb.Append("Table Name:");
225             sb.Append(this.m_tableExtent.Name);
226
227             Console.WriteLine(sb.ToString());
228             foreach (StorageConditionPropertyMapping conditionMap in m_conditionProperties.Values)
229                 (conditionMap).Print(index + 5);
230             foreach (StoragePropertyMapping propertyMapping in m_properties)
231             {
232                 propertyMapping.Print(index + 5);
233             }
234         }
235         #endregion
236     }
237 }