e59c739447dde38212cbc09f8df6abeeca43f649
[mono.git] / mcs / class / referencesource / System.Data.Entity / System / Data / EntityModel / SchemaObjectModel / CollectionTypeElement.cs
1 //---------------------------------------------------------------------
2 // <copyright file="CollectionTypeElement.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.Entity;
15     using System.Data.Metadata.Edm;
16     using System.Diagnostics;
17     using System.Text;
18     using System.Xml;
19     using Som = System.Data.EntityModel.SchemaObjectModel;
20
21     /// <summary>
22     /// class representing the Schema element in the schema
23     /// </summary>
24     internal class CollectionTypeElement : ModelFunctionTypeElement
25     {
26         private ModelFunctionTypeElement _typeSubElement = null;
27         
28         #region constructor
29         /// <summary>
30         /// 
31         /// </summary>
32         /// <param name="parentElement"></param>
33         internal CollectionTypeElement(SchemaElement parentElement)
34             : base(parentElement)
35         {
36
37         }
38         #endregion
39
40         internal ModelFunctionTypeElement SubElement
41         {
42             get { return _typeSubElement; }
43         }
44
45         protected override bool HandleAttribute(XmlReader reader)
46         {
47             if (base.HandleAttribute(reader))
48             {
49                 return true;
50             }
51             else if (CanHandleAttribute(reader, XmlConstants.ElementType))
52             {
53                 HandleElementTypeAttribute(reader);
54                 return true;
55             }
56
57             return false;
58         }
59
60         protected void HandleElementTypeAttribute(XmlReader reader)
61         {
62             Debug.Assert(reader != null);
63
64             string type;
65             if (!Utils.GetString(Schema, reader, out type))
66                 return;
67
68             if (!Utils.ValidateDottedName(Schema, reader, type))
69                 return;
70
71             _unresolvedType = type;
72         }
73
74         protected override bool HandleElement(XmlReader reader)
75         {
76             if (CanHandleElement(reader, XmlConstants.CollectionType))
77             {
78                 HandleCollectionTypeElement(reader);
79                 return true;
80             }
81             else if (CanHandleElement(reader, XmlConstants.ReferenceType))
82             {
83                 HandleReferenceTypeElement(reader);
84                 return true;
85             }
86             else if (CanHandleElement(reader, XmlConstants.TypeRef))
87             {
88                 HandleTypeRefElement(reader);
89                 return true;
90             }
91             else if (CanHandleElement(reader, XmlConstants.RowType))
92             {
93                 HandleRowTypeElement(reader);
94                 return true;
95             }
96
97             return false;
98         }
99
100
101         protected void HandleCollectionTypeElement(XmlReader reader)
102         {
103             Debug.Assert(reader != null);
104
105             var subElement = new CollectionTypeElement(this);
106             subElement.Parse(reader);
107             _typeSubElement = subElement;
108         }
109
110         protected void HandleReferenceTypeElement(XmlReader reader)
111         {
112             Debug.Assert(reader != null);
113
114             var subElement = new ReferenceTypeElement(this);
115             subElement.Parse(reader);
116             _typeSubElement = subElement;
117         }
118
119         protected void HandleTypeRefElement(XmlReader reader)
120         {
121             Debug.Assert(reader != null);
122
123             var subElement = new TypeRefElement(this);
124             subElement.Parse(reader);
125             _typeSubElement = subElement;
126         }
127
128         protected void HandleRowTypeElement(XmlReader reader)
129         {
130             Debug.Assert(reader != null);
131
132             var subElement = new RowTypeElement(this);
133             subElement.Parse(reader);
134             _typeSubElement = subElement;
135         }
136
137         internal override void ResolveTopLevelNames()
138         {
139             if (_typeSubElement != null)
140             {
141                 _typeSubElement.ResolveTopLevelNames();
142             }
143
144             // Can't be "else if" because element could have attribute AND sub-element, 
145             // in which case semantic validation won't work unless it has resolved both (so _type is not null)
146             if( _unresolvedType != null) 
147             {
148                 base.ResolveTopLevelNames();
149             }
150
151         }
152
153         internal override void WriteIdentity(StringBuilder builder)
154         {
155
156             if (UnresolvedType != null && !UnresolvedType.Trim().Equals(String.Empty))
157             {
158                 builder.Append("Collection(" + UnresolvedType + ")");
159             }
160             else
161             {
162                 builder.Append("Collection(");
163                 _typeSubElement.WriteIdentity(builder);
164                 builder.Append(")");
165             }
166         }
167
168         internal override TypeUsage GetTypeUsage()
169         {
170             if (_typeUsage != null)
171             {
172                 return _typeUsage;
173             }
174             Debug.Assert(_typeSubElement != null, "For attributes typeusage should have been resolved");
175             
176             if (_typeSubElement != null)
177             {
178                 CollectionType collectionType = new CollectionType(_typeSubElement.GetTypeUsage());
179
180                 collectionType.AddMetadataProperties(this.OtherContent);
181                 _typeUsage = TypeUsage.Create(collectionType);
182             }
183             return _typeUsage;
184         }
185
186         internal override bool ResolveNameAndSetTypeUsage(Converter.ConversionCache convertedItemCache, Dictionary<Som.SchemaElement, GlobalItem> newGlobalItems)
187         {
188             if (_typeUsage == null)
189             {
190                 if (_typeSubElement != null) //Has sub-elements
191                 {
192                     return _typeSubElement.ResolveNameAndSetTypeUsage(convertedItemCache, newGlobalItems);
193                 }
194                 else //Does not have sub-elements; try to resolve
195                 {
196                     if (_type is ScalarType) //Create and store type usage for scalar type
197                     {
198                         _typeUsageBuilder.ValidateAndSetTypeUsage(_type as ScalarType, false);
199                         _typeUsage = TypeUsage.Create(new CollectionType(_typeUsageBuilder.TypeUsage));
200                         return true;
201                     }
202                     else  //Try to resolve edm type. If not now, it will resolve in the second pass
203                     {
204                         EdmType edmType = (EdmType)Converter.LoadSchemaElement(_type, _type.Schema.ProviderManifest, convertedItemCache, newGlobalItems);
205                         if (edmType != null)
206                         {
207                             _typeUsageBuilder.ValidateAndSetTypeUsage(edmType, false); //use typeusagebuilder so dont lose facet information
208                             _typeUsage = TypeUsage.Create(new CollectionType(_typeUsageBuilder.TypeUsage));
209                         }
210
211                         return _typeUsage != null;
212                     }
213                 }
214             }
215             return true;
216         }
217
218         internal override void Validate()
219         {
220             base.Validate();
221
222             ValidationHelper.ValidateFacets(this, _type, _typeUsageBuilder);
223             ValidationHelper.ValidateTypeDeclaration(this, _type, _typeSubElement);
224
225             if (_typeSubElement != null)
226             {
227                 _typeSubElement.Validate();
228             }
229         }
230     }
231 }