Update Reference Sources to .NET Framework 4.6.1
[mono.git] / mcs / class / referencesource / System.Data.Entity / System / Data / EntityModel / SchemaObjectModel / RowTypePropertyElement.cs
1 //---------------------------------------------------------------------
2 // <copyright file="RowTypePropertyElement.cs" company="Microsoft">
3 //      Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //
6 // @owner       [....]
7 // @backupOwner [....]
8 //---------------------------------------------------------------------
9
10 namespace System.Data.EntityModel.SchemaObjectModel
11 {
12     using System;
13     using System.Collections.Generic;
14     using System.Data.Entity;
15     using System.Data.Metadata.Edm;
16     using System.Diagnostics;
17     using System.Globalization;
18     using System.Text;
19     using System.Xml;
20     using Som = System.Data.EntityModel.SchemaObjectModel;
21
22     class RowTypePropertyElement : ModelFunctionTypeElement
23     {
24         private ModelFunctionTypeElement _typeSubElement = null;
25         private bool _isRefType = false;
26         private CollectionKind _collectionKind = CollectionKind.None;
27
28         internal RowTypePropertyElement(SchemaElement parentElement)
29             : base(parentElement)
30         {
31             _typeUsageBuilder = new TypeUsageBuilder(this);
32         }
33
34         internal override void ResolveTopLevelNames()
35         {
36             if (_unresolvedType != null)
37             {
38                 base.ResolveTopLevelNames();
39             }
40
41             if (_typeSubElement != null)
42             {
43                 _typeSubElement.ResolveTopLevelNames();
44             }
45         }
46
47         protected override bool HandleAttribute(XmlReader reader)
48         {
49             if (base.HandleAttribute(reader))
50             {
51                 return true;
52             }
53             else if (CanHandleAttribute(reader, XmlConstants.TypeElement))
54             {
55                 HandleTypeAttribute(reader);
56                 return true;
57             }
58
59             return false;
60         }
61
62         protected void HandleTypeAttribute(XmlReader reader)
63         {
64             Debug.Assert(reader != null);
65
66             string type;
67             if (!Utils.GetString(Schema, reader, out type))
68                 return;
69
70             TypeModifier typeModifier;
71             Function.RemoveTypeModifier(ref type, out typeModifier, out _isRefType);
72
73             switch (typeModifier)
74             {
75                 case TypeModifier.Array:
76                     _collectionKind = CollectionKind.Bag;
77                     break;
78                 default:
79                     Debug.Assert(typeModifier == TypeModifier.None, string.Format(CultureInfo.CurrentCulture, "Type is not valid for property {0}: {1}. The modifier for the type cannot be used in this context.", FQName, reader.Value));
80                     break;
81             }
82
83             if (!Utils.ValidateDottedName(Schema, reader, type))
84                 return;
85
86             _unresolvedType = type;
87         }
88
89         protected override bool HandleElement(XmlReader reader)
90         {
91             if (CanHandleElement(reader, XmlConstants.CollectionType))
92             {
93                 HandleCollectionTypeElement(reader);
94                 return true;
95             }
96             else if (CanHandleElement(reader, XmlConstants.ReferenceType))
97             {
98                 HandleReferenceTypeElement(reader);
99                 return true;
100             }
101             else if (CanHandleElement(reader, XmlConstants.TypeRef))
102             {
103                 HandleTypeRefElement(reader);
104                 return true;
105             }
106             else if (CanHandleElement(reader, XmlConstants.RowType))
107             {
108                 HandleRowTypeElement(reader);
109                 return true;
110             }
111
112             return false;
113         }
114
115         protected void HandleCollectionTypeElement(XmlReader reader)
116         {
117             Debug.Assert(reader != null);
118
119             var subElement = new CollectionTypeElement(this);
120             subElement.Parse(reader);
121             _typeSubElement = subElement;
122         }
123
124         protected void HandleReferenceTypeElement(XmlReader reader)
125         {
126             Debug.Assert(reader != null);
127
128             var subElement = new ReferenceTypeElement(this);
129             subElement.Parse(reader);
130             _typeSubElement = subElement;
131         }
132
133         protected void HandleTypeRefElement(XmlReader reader)
134         {
135             Debug.Assert(reader != null);
136
137             var subElement = new TypeRefElement(this);
138             subElement.Parse(reader);
139             _typeSubElement = subElement;
140         }
141
142         protected void HandleRowTypeElement(XmlReader reader)
143         {
144             Debug.Assert(reader != null);
145
146             var subElement = new RowTypeElement(this);
147             subElement.Parse(reader);
148             _typeSubElement = subElement;
149         }
150
151         internal override void WriteIdentity(StringBuilder builder)
152         {
153             builder.Append("Property(");
154
155             if (UnresolvedType != null && !UnresolvedType.Trim().Equals(String.Empty))
156             {
157                 if (_collectionKind != CollectionKind.None)
158                 {
159                     builder.Append("Collection(" + UnresolvedType + ")");
160                 }
161                 else if (_isRefType)
162                 {
163                     builder.Append("Ref(" + UnresolvedType + ")");
164                 }
165                 else
166                 {
167                     builder.Append(UnresolvedType);
168                 }
169             }
170             else
171             {
172                 _typeSubElement.WriteIdentity(builder);
173             }
174
175             builder.Append(")");
176         }
177
178         internal override TypeUsage GetTypeUsage()
179         {
180             if (_typeUsage != null)
181             {
182                 return _typeUsage;
183             }
184             Debug.Assert(_typeSubElement != null, "For attributes typeusage should have been resolved");
185
186             if (_typeSubElement != null)
187             {
188                 _typeUsage = _typeSubElement.GetTypeUsage();
189             }
190             return _typeUsage;
191         }
192
193         internal override bool ResolveNameAndSetTypeUsage(Converter.ConversionCache convertedItemCache, Dictionary<Som.SchemaElement, GlobalItem> newGlobalItems)
194         {
195             if (_typeUsage == null)
196             {
197                 if (_typeSubElement != null) //Has sub-elements
198                 {
199                     return _typeSubElement.ResolveNameAndSetTypeUsage(convertedItemCache, newGlobalItems);
200                 }
201                 else //Does not have sub-elements; try to resolve
202                 {
203                     if (_type is ScalarType) //Create and store type usage for scalar type
204                     {
205                         _typeUsageBuilder.ValidateAndSetTypeUsage(_type as ScalarType, false);
206                         _typeUsage = _typeUsageBuilder.TypeUsage;
207                     }
208                     else  //Try to resolve edm type. If not now, it will resolve in the second pass
209                     {
210                         EdmType edmType = (EdmType)Converter.LoadSchemaElement(_type, _type.Schema.ProviderManifest, convertedItemCache, newGlobalItems);
211                         if (edmType != null)
212                         {
213                             if (_isRefType)
214                             {
215                                 EntityType entityType = edmType as EntityType;
216                                 Debug.Assert(entityType != null);
217                                 _typeUsage = TypeUsage.Create(new RefType(entityType));
218                             }
219                             else
220                             {
221                                 _typeUsageBuilder.ValidateAndSetTypeUsage(edmType, false); //use typeusagebuilder so dont lose facet information
222                                 _typeUsage = _typeUsageBuilder.TypeUsage;
223                             }
224                         }
225                     }
226                     if (_collectionKind != CollectionKind.None)
227                     {
228                         _typeUsage = TypeUsage.Create(new CollectionType(_typeUsage));
229                     }
230
231                     return _typeUsage != null;
232                 }
233             }
234             return true;
235         }
236
237         /// <summary>
238         /// True is property is scalar, otherwise false.
239         /// During validation (after all types have been resolved).
240         /// </summary>
241         internal bool ValidateIsScalar()
242         {
243             if (_type != null)
244             {
245                 if (_type is ScalarType == false || _isRefType || _collectionKind != CollectionKind.None)
246                 {
247                     return false;
248                 }
249             }
250             else if (_typeSubElement != null)
251             {
252                 if (_typeSubElement.Type is ScalarType == false)
253                 {
254                     return false;
255                 }
256             }
257             return true;
258         }
259
260         internal override void Validate()
261         {
262             base.Validate();
263
264             ValidationHelper.ValidateFacets(this, _type, _typeUsageBuilder);
265             ValidationHelper.ValidateTypeDeclaration(this, _type, _typeSubElement);
266
267             if (_isRefType)
268             {
269                 ValidationHelper.ValidateRefType(this, _type);
270             }
271
272             if (_typeSubElement != null)
273             {
274                 _typeSubElement.Validate();
275             }
276         }
277     }
278 }