1 //---------------------------------------------------------------------
2 // <copyright file="RowTypePropertyElement.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
8 //---------------------------------------------------------------------
10 namespace System.Data.EntityModel.SchemaObjectModel
13 using System.Collections.Generic;
14 using System.Data.Entity;
15 using System.Data.Metadata.Edm;
16 using System.Diagnostics;
17 using System.Globalization;
20 using Som = System.Data.EntityModel.SchemaObjectModel;
22 class RowTypePropertyElement : ModelFunctionTypeElement
24 private ModelFunctionTypeElement _typeSubElement = null;
25 private bool _isRefType = false;
26 private CollectionKind _collectionKind = CollectionKind.None;
28 internal RowTypePropertyElement(SchemaElement parentElement)
31 _typeUsageBuilder = new TypeUsageBuilder(this);
34 internal override void ResolveTopLevelNames()
36 if (_unresolvedType != null)
38 base.ResolveTopLevelNames();
41 if (_typeSubElement != null)
43 _typeSubElement.ResolveTopLevelNames();
47 protected override bool HandleAttribute(XmlReader reader)
49 if (base.HandleAttribute(reader))
53 else if (CanHandleAttribute(reader, XmlConstants.TypeElement))
55 HandleTypeAttribute(reader);
62 protected void HandleTypeAttribute(XmlReader reader)
64 Debug.Assert(reader != null);
67 if (!Utils.GetString(Schema, reader, out type))
70 TypeModifier typeModifier;
71 Function.RemoveTypeModifier(ref type, out typeModifier, out _isRefType);
75 case TypeModifier.Array:
76 _collectionKind = CollectionKind.Bag;
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));
83 if (!Utils.ValidateDottedName(Schema, reader, type))
86 _unresolvedType = type;
89 protected override bool HandleElement(XmlReader reader)
91 if (CanHandleElement(reader, XmlConstants.CollectionType))
93 HandleCollectionTypeElement(reader);
96 else if (CanHandleElement(reader, XmlConstants.ReferenceType))
98 HandleReferenceTypeElement(reader);
101 else if (CanHandleElement(reader, XmlConstants.TypeRef))
103 HandleTypeRefElement(reader);
106 else if (CanHandleElement(reader, XmlConstants.RowType))
108 HandleRowTypeElement(reader);
115 protected void HandleCollectionTypeElement(XmlReader reader)
117 Debug.Assert(reader != null);
119 var subElement = new CollectionTypeElement(this);
120 subElement.Parse(reader);
121 _typeSubElement = subElement;
124 protected void HandleReferenceTypeElement(XmlReader reader)
126 Debug.Assert(reader != null);
128 var subElement = new ReferenceTypeElement(this);
129 subElement.Parse(reader);
130 _typeSubElement = subElement;
133 protected void HandleTypeRefElement(XmlReader reader)
135 Debug.Assert(reader != null);
137 var subElement = new TypeRefElement(this);
138 subElement.Parse(reader);
139 _typeSubElement = subElement;
142 protected void HandleRowTypeElement(XmlReader reader)
144 Debug.Assert(reader != null);
146 var subElement = new RowTypeElement(this);
147 subElement.Parse(reader);
148 _typeSubElement = subElement;
151 internal override void WriteIdentity(StringBuilder builder)
153 builder.Append("Property(");
155 if (UnresolvedType != null && !UnresolvedType.Trim().Equals(String.Empty))
157 if (_collectionKind != CollectionKind.None)
159 builder.Append("Collection(" + UnresolvedType + ")");
163 builder.Append("Ref(" + UnresolvedType + ")");
167 builder.Append(UnresolvedType);
172 _typeSubElement.WriteIdentity(builder);
178 internal override TypeUsage GetTypeUsage()
180 if (_typeUsage != null)
184 Debug.Assert(_typeSubElement != null, "For attributes typeusage should have been resolved");
186 if (_typeSubElement != null)
188 _typeUsage = _typeSubElement.GetTypeUsage();
193 internal override bool ResolveNameAndSetTypeUsage(Converter.ConversionCache convertedItemCache, Dictionary<Som.SchemaElement, GlobalItem> newGlobalItems)
195 if (_typeUsage == null)
197 if (_typeSubElement != null) //Has sub-elements
199 return _typeSubElement.ResolveNameAndSetTypeUsage(convertedItemCache, newGlobalItems);
201 else //Does not have sub-elements; try to resolve
203 if (_type is ScalarType) //Create and store type usage for scalar type
205 _typeUsageBuilder.ValidateAndSetTypeUsage(_type as ScalarType, false);
206 _typeUsage = _typeUsageBuilder.TypeUsage;
208 else //Try to resolve edm type. If not now, it will resolve in the second pass
210 EdmType edmType = (EdmType)Converter.LoadSchemaElement(_type, _type.Schema.ProviderManifest, convertedItemCache, newGlobalItems);
215 EntityType entityType = edmType as EntityType;
216 Debug.Assert(entityType != null);
217 _typeUsage = TypeUsage.Create(new RefType(entityType));
221 _typeUsageBuilder.ValidateAndSetTypeUsage(edmType, false); //use typeusagebuilder so dont lose facet information
222 _typeUsage = _typeUsageBuilder.TypeUsage;
226 if (_collectionKind != CollectionKind.None)
228 _typeUsage = TypeUsage.Create(new CollectionType(_typeUsage));
231 return _typeUsage != null;
238 /// True is property is scalar, otherwise false.
239 /// During validation (after all types have been resolved).
241 internal bool ValidateIsScalar()
245 if (_type is ScalarType == false || _isRefType || _collectionKind != CollectionKind.None)
250 else if (_typeSubElement != null)
252 if (_typeSubElement.Type is ScalarType == false)
260 internal override void Validate()
264 ValidationHelper.ValidateFacets(this, _type, _typeUsageBuilder);
265 ValidationHelper.ValidateTypeDeclaration(this, _type, _typeSubElement);
269 ValidationHelper.ValidateRefType(this, _type);
272 if (_typeSubElement != null)
274 _typeSubElement.Validate();