Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System.Data.Entity / System / Data / EntityModel / SchemaObjectModel / StructuredProperty.cs
1 //---------------------------------------------------------------------
2 // <copyright file="StructuredProperty.cs" company="Microsoft">
3 //      Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //
6 // @owner       Microsoft
7 // @backupOwner Microsoft
8 //---------------------------------------------------------------------
9
10 namespace System.Data.EntityModel.SchemaObjectModel
11 {
12     using System;
13     using System.Collections.Generic;
14     using System.Data.Metadata.Edm;
15     using System.Diagnostics;
16     using System.Xml;
17
18     /// <summary>
19     /// Summary description for StructuredProperty.
20     /// </summary>
21     internal class StructuredProperty : Property
22     {
23         #region Instance Fields
24         private SchemaType _type = null;
25         private string _unresolvedType = null;
26         
27         // Facets
28         private TypeUsageBuilder _typeUsageBuilder;
29
30         //Type of the Collection. By Default Single, and in case of Collections, will be either Bag or List
31         private CollectionKind _collectionKind = CollectionKind.None;
32
33         #endregion
34         #region Static Fields
35         
36         //private static System.Text.RegularExpressions.Regex _binaryValueValidator = new System.Text.RegularExpressions.Regex("0[xX][0-9a-fA-F]+");
37         #endregion
38         #region Public Methods
39
40         /// <summary>
41         /// 
42         /// </summary>
43         /// <param name="parentElement"></param>
44         internal StructuredProperty(StructuredType parentElement)
45             : base(parentElement)
46         {
47             _typeUsageBuilder = new TypeUsageBuilder(this);
48         }
49
50         #endregion
51         #region Public Properties
52
53         /// <summary>
54         /// 
55         /// </summary>
56         public override SchemaType Type
57         {
58             get
59             {
60                 return _type;
61             }
62         }
63
64         /// <summary>
65         /// Returns a TypeUsage that represent this property. 
66         /// </summary>
67         public TypeUsage TypeUsage
68         {
69             get
70             {
71                 return _typeUsageBuilder.TypeUsage;
72             }
73         }
74         
75         /// <summary>
76         /// The nullablity of this property.
77         /// </summary>
78         public bool Nullable
79         {
80             get
81             {
82                 return _typeUsageBuilder.Nullable;
83             }
84         }
85
86         /// <summary>
87         /// 
88         /// </summary>
89         public string Default
90         {
91             get
92             {
93                 return _typeUsageBuilder.Default;
94             }
95         }
96
97         /// <summary>
98         /// 
99         /// </summary>
100         public object DefaultAsObject
101         {
102             get
103             {
104                 return _typeUsageBuilder.DefaultAsObject;
105             }
106         }
107
108
109         /// <summary>
110         /// Specifies the type of the Collection. 
111         /// By Default this is Single( i.e. not a Collection.
112         /// And in case of Collections, will be either Bag or List
113         /// </summary>
114         public CollectionKind CollectionKind
115         {
116             get
117             {
118                 return _collectionKind;
119             }
120         }
121
122         #endregion
123         #region Internal Methods
124
125         /// <summary>
126         /// 
127         /// </summary>
128         internal override void ResolveTopLevelNames()
129         {
130             base.ResolveTopLevelNames();
131
132             if (_type != null)
133             {
134                 return;
135             }
136
137             _type = ResolveType(UnresolvedType);
138
139             _typeUsageBuilder.ValidateDefaultValue(_type);
140
141             ScalarType scalar = _type as ScalarType;
142             if (scalar != null)
143             {
144                 _typeUsageBuilder.ValidateAndSetTypeUsage(scalar, true);
145             }
146         }
147
148         // 
149
150
151
152         internal void EnsureEnumTypeFacets(Converter.ConversionCache convertedItemCache, Dictionary<SchemaElement, GlobalItem> newGlobalItems)
153         {
154             Debug.Assert(Type is SchemaEnumType);
155             EdmType propertyType = (EdmType)Converter.LoadSchemaElement(Type, Type.Schema.ProviderManifest, convertedItemCache, newGlobalItems);
156             _typeUsageBuilder.ValidateAndSetTypeUsage(propertyType, false);//use typeusagebuilder so dont lose facet information
157         }
158
159         /// <summary>
160         /// Resolve the type string to a SchemaType object
161         /// </summary>
162         /// <param name="typeName"></param>
163         /// <returns></returns>
164         protected virtual SchemaType ResolveType(string typeName)
165         {
166             SchemaType element;
167             if (!Schema.ResolveTypeName(this, typeName, out element))
168             {
169                 return null;
170             }
171
172             if (!(element is SchemaComplexType) && !(element is ScalarType) && !(element is SchemaEnumType))
173             {
174                 AddError(ErrorCode.InvalidPropertyType, EdmSchemaErrorSeverity.Error,
175                     System.Data.Entity.Strings.InvalidPropertyType(UnresolvedType));
176                 return null;
177             }
178
179             SchemaType structuredType = element as SchemaType;
180
181             return element;
182         }
183         #endregion
184
185         #region Internal Properties
186         /// <summary>
187         /// 
188         /// </summary>
189         /// <value></value>
190         internal string UnresolvedType
191         {
192             get
193             {
194                 return _unresolvedType;
195             }
196             set
197             {
198                 _unresolvedType = value;
199             }
200         }
201
202         #endregion
203         #region Protected Methods
204
205         internal override void Validate()
206         {
207             base.Validate();
208             //Non Complex Collections are not supported
209             if ((_collectionKind == CollectionKind.Bag) ||
210                 (_collectionKind == CollectionKind.List))
211             {
212                 Debug.Assert(Schema.SchemaVersion != XmlConstants.EdmVersionForV1,
213                     "CollctionKind Attribute is not supported in EDM V1");
214             }
215
216             var schemaEnumType = this._type as SchemaEnumType;
217             if (schemaEnumType != null)
218             {
219                 this._typeUsageBuilder.ValidateEnumFacets(schemaEnumType);
220             } 
221             else if (Nullable && (this.Schema.SchemaVersion != XmlConstants.EdmVersionForV1_1)
222                 && (this._type is SchemaComplexType))
223             {
224                 //Nullable Complex Types are not supported in V1.0, V2 and V3
225                 AddError(ErrorCode.NullableComplexType, EdmSchemaErrorSeverity.Error,
226                     System.Data.Entity.Strings.ComplexObject_NullableComplexTypesNotSupported(this.FQName));
227             }
228         }
229
230         #endregion
231         #region Protected Properties
232         protected override bool HandleAttribute(XmlReader reader)
233         {
234             if (base.HandleAttribute(reader))
235             {
236                 return true;
237             }
238             else if (CanHandleAttribute(reader, XmlConstants.TypeElement))
239             {
240                 HandleTypeAttribute(reader);
241                 return true;
242             }
243             else if (CanHandleAttribute(reader, XmlConstants.CollectionKind))
244             {
245                 HandleCollectionKindAttribute(reader);
246                 return true;
247             }
248             else if (_typeUsageBuilder.HandleAttribute(reader))
249             {
250                 return true;
251             }
252             return false;
253         }
254         #endregion
255         #region Private Methods
256         /// <summary>
257         /// 
258         /// </summary>
259         /// <param name="reader"></param>
260         private void HandleTypeAttribute(XmlReader reader)
261         {
262             if (UnresolvedType != null)
263             {
264                 AddError(ErrorCode.AlreadyDefined, EdmSchemaErrorSeverity.Error, reader,
265                     System.Data.Entity.Strings.PropertyTypeAlreadyDefined(reader.Name));
266                 return;
267             }
268
269             string type;
270             if (!Utils.GetDottedName(Schema, reader, out type))
271                 return;
272
273             UnresolvedType = type;
274         }
275
276         /// <summary>
277         /// Handles the Multiplicity attribute on the property.
278         /// </summary>
279         /// <param name="reader"></param>
280         private void HandleCollectionKindAttribute(XmlReader reader)
281         {
282             string value = reader.Value;
283             if (value == XmlConstants.CollectionKind_None)
284             {
285                 _collectionKind = CollectionKind.None;
286             }
287             else
288             {
289                 if (value == XmlConstants.CollectionKind_List)
290                 {
291                     _collectionKind = CollectionKind.List;
292                 }
293                 else if (value == XmlConstants.CollectionKind_Bag)
294                 {
295                     _collectionKind = CollectionKind.Bag;
296                 }
297                 else
298                 {
299                     Debug.Fail("Xsd should have changed", "XSD validation should have ensured that" +
300                         " Multiplicity attribute has only 'None' or 'Bag' or 'List' as the values");
301                     return;
302                 }
303             }
304         }
305
306         #endregion
307     }
308 }