Schema.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataEntity / System / Data / EntityModel / SchemaObjectModel / Schema.cs / 1305376 / Schema.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner       [....]
// @backupOwner [....] 
//--------------------------------------------------------------------- 

using System; 
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Data; 
using System.Data.Metadata.Edm;
using System.Diagnostics; 
using System.Globalization; 
using System.Xml;
using System.Xml.Schema; 
using System.IO;
using System.Data.Common;
using System.Data.Common.Utils;
using System.Data.Objects.DataClasses; 
using System.Text;
using System.Data.Entity; 
using System.Linq; 

namespace System.Data.EntityModel.SchemaObjectModel 
{
    /// 
    /// class representing the Schema element in the schema
    ///  
    [System.Diagnostics.DebuggerDisplay("Namespace={Namespace}, PublicKeyToken={PublicKeyToken}, Version={Version}")]
    internal class Schema : SchemaElement 
    { 

        #region Instance Fields 
        private const int RootDepth = 2;
        // if adding properties also add to InitializeObject()!
        private List _errors = new List();
        // We need to keep track of functions seperately, since we can't deduce the strong name of the function, 
        // until we have resolved the parameter names. Hence we keep track of functions seperately and add them
        // to the schema types list, in the validate phase 
        private List _functions = null; 

        private AliasResolver _aliasResolver = null; 
        private string _location = null;
        private string _alias = null;
        protected string _namespaceName = null;
        private string _schemaXmlNamespace = null; 
        private List _schemaTypes = null;
 
        private int _depth = 0; // recursion depth in Parse used by *Handlers to know which hander set to set 
        private double _schemaVersion = XmlConstants.UndefinedVersion;
        private SchemaManager _schemaManager; 
        #endregion

        #region Static Fields
        private static IList _emptyPathList = new List(0).AsReadOnly(); 
        #endregion
 
        #region Public Methods 

        public Schema(SchemaManager schemaManager) 
            : base(null)
        {
            Debug.Assert(schemaManager != null, "SchemaManager parameter should never be null");
            _schemaManager = schemaManager; 
            _errors = new List();
        } 
 
        internal IList Resolve()
        { 
            ResolveTopLevelNames();
            if (_errors.Count != 0)
            {
                return ResetErrors(); 
            }
            ResolveSecondLevelNames(); 
            return ResetErrors(); 
        }
 
        internal IList ValidateSchema()
        {
            Validate();
            return ResetErrors(); 
        }
 
        internal void AddError(EdmSchemaError error) 
        {
            _errors.Add(error); 
        }

        /// 
        /// Populate the schema object from a schema 
        /// 
        /// TextReader containing the schema xml definition 
        /// Uri containing path to a schema file (may be null) 
        /// list of errors
        internal IList Parse(XmlReader sourceReader, string sourceLocation) 
        {
            // We don't Assert (sourceReader != null) here any more because third-party
            // providers that extend XmlEnabledProvidermanifest could hit this code. The
            // following code eventually detects the anomaly and a ProviderIncompatible 
            // exception is thrown (which is the right thing to do in such cases).
 
            XmlReader wrappedReader = null; 
            try
            { 
                // user specified a stream to read from, read from it.
                // The Uri is just used to identify the stream in errors.
                XmlReaderSettings readerSettings = CreateXmlReaderSettings();
                wrappedReader = XmlReader.Create(sourceReader, readerSettings); 
                return InternalParse(wrappedReader, sourceLocation);
 
            } 
            catch (System.IO.IOException ex)
            { 
                AddError(ErrorCode.IOException, EdmSchemaErrorSeverity.Error, sourceReader, ex);
            }

            // do not close the reader here (SQLBUDT 522950) 

            return ResetErrors(); 
        } 

        ///  
        /// Populate the schema object from a schema
        /// 
        /// TextReader containing the schema xml definition
        /// Uri containing path to a schema file (may be null) 
        /// list of errors
        private IList InternalParse(XmlReader sourceReader, string sourceLocation) 
        { 
            Debug.Assert(sourceReader != null, "sourceReader parameter is null");
 
            // these need to be set before any calls to AddError are made.
            Schema = this;
            Location = sourceLocation;
 
            try
            { 
                // to make life simpler, we skip down to the first/root element, unless we're 
                // already there
                if (sourceReader.NodeType != XmlNodeType.Element) 
                {
                    while (sourceReader.Read() && sourceReader.NodeType != XmlNodeType.Element)
                    {
                    } 
                }
                GetPositionInfo(sourceReader); 
 
                List expectedNamespaces = SomSchemaSetHelper.GetPrimarySchemaNamespaces(DataModel);
 
                // the root element needs to be either TDL or Schema in our namespace
                if (sourceReader.EOF)
                {
                    if (sourceLocation != null) 
                    {
                        AddError(ErrorCode.EmptyFile, EdmSchemaErrorSeverity.Error, System.Data.Entity.Strings.EmptyFile(sourceLocation)); 
                    } 
                    else
                    { 
                        AddError(ErrorCode.EmptyFile, EdmSchemaErrorSeverity.Error, System.Data.Entity.Strings.EmptySchemaTextReader);
                    }
                }
                else if (!expectedNamespaces.Contains(sourceReader.NamespaceURI)) 
                {
                    Func messageFormat = Strings.UnexpectedRootElement; 
                    if (string.IsNullOrEmpty(sourceReader.NamespaceURI)) 
                        messageFormat = Strings.UnexpectedRootElementNoNamespace;
                    String expectedNamespacesString =  Helper.GetCommaDelimitedString(expectedNamespaces); 
                    AddError(ErrorCode.UnexpectedXmlElement, EdmSchemaErrorSeverity.Error, messageFormat(sourceReader.NamespaceURI, sourceReader.LocalName, expectedNamespacesString));
                }
                else
                { 
                    this.SchemaXmlNamespace = sourceReader.NamespaceURI;
                    if (DataModel == SchemaDataModelOption.EntityDataModel) 
                    { 
                        if (this.SchemaXmlNamespace == XmlConstants.ModelNamespace_1)
                        { 
                            SchemaVersion = XmlConstants.EdmVersionForV1;
                        }
                        else if (this.SchemaXmlNamespace == XmlConstants.ModelNamespace_1_1)
                        { 
                            SchemaVersion = XmlConstants.EdmVersionForV1_1;
                        } 
                        else 
                        {
                            Debug.Assert(this.SchemaXmlNamespace == XmlConstants.ModelNamespace_2, "Unknown namespace in CSDL"); 
                            SchemaVersion = XmlConstants.EdmVersionForV2;
                        }
                    }
                    else if (DataModel == SchemaDataModelOption.ProviderDataModel) 
                    {
                        if (this.SchemaXmlNamespace == XmlConstants.TargetNamespace_1) 
                        { 
                            SchemaVersion = XmlConstants.StoreVersionForV1;
                        } 
                        else
                        {
                            Debug.Assert(this.SchemaXmlNamespace == XmlConstants.TargetNamespace_2, "Unknown namespace in SSDL");
                            SchemaVersion = XmlConstants.StoreVersionForV2; 
                        }
                    } 
 
                    switch (sourceReader.LocalName)
                    { 
                        case "Schema":
                        case "ProviderManifest":
                            HandleTopLevelSchemaElement(sourceReader);
                            // this forces the reader to look beyond this top 
                            // level element, and complain if there is another one.
                            sourceReader.Read(); 
                            break; 
                        default:
                            AddError(ErrorCode.UnexpectedXmlElement, EdmSchemaErrorSeverity.Error, System.Data.Entity.Strings.UnexpectedRootElement(sourceReader.NamespaceURI, sourceReader.LocalName, SchemaXmlNamespace)); 
                            break;
                    }
                }
            } 
            catch (InvalidOperationException ex)
            { 
                AddError(ErrorCode.InternalError, EdmSchemaErrorSeverity.Error, ex.Message); 
            }
            catch (System.UnauthorizedAccessException ex) 
            {
                AddError(ErrorCode.UnauthorizedAccessException, EdmSchemaErrorSeverity.Error, sourceReader, ex);
            }
            catch (System.IO.IOException ex) 
            {
                AddError(ErrorCode.IOException, EdmSchemaErrorSeverity.Error, sourceReader, ex); 
            } 
            catch (System.Security.SecurityException ex)
            { 
                AddError(ErrorCode.SecurityError, EdmSchemaErrorSeverity.Error, sourceReader, ex);
            }
            catch (XmlException ex)
            { 
                AddError(ErrorCode.XmlError, EdmSchemaErrorSeverity.Error, sourceReader, ex);
            } 
 
            return ResetErrors();
        } 

        internal static XmlReaderSettings CreateEdmStandardXmlReaderSettings()
        {
            XmlReaderSettings readerSettings = new XmlReaderSettings(); 

            readerSettings.CheckCharacters = true; 
            readerSettings.CloseInput = false; 
            readerSettings.IgnoreWhitespace = true;
            readerSettings.ConformanceLevel = ConformanceLevel.Auto; 
            readerSettings.IgnoreComments = true;
            readerSettings.IgnoreProcessingInstructions = true;
            readerSettings.DtdProcessing = DtdProcessing.Prohibit;
 
            // remove flags
            // the ProcessInlineSchema, and ProcessSchemaLocation flags must be removed for the same 
            // xsd schema to be used on multiple threads 
            readerSettings.ValidationFlags &= ~System.Xml.Schema.XmlSchemaValidationFlags.ProcessIdentityConstraints;
            readerSettings.ValidationFlags &= ~System.Xml.Schema.XmlSchemaValidationFlags.ProcessSchemaLocation; 
            readerSettings.ValidationFlags &= ~System.Xml.Schema.XmlSchemaValidationFlags.ProcessInlineSchema;

            return readerSettings;
        } 

        private XmlReaderSettings CreateXmlReaderSettings() 
        { 
            XmlReaderSettings readerSettings = CreateEdmStandardXmlReaderSettings();
 
            // add flags
            readerSettings.ValidationFlags |= System.Xml.Schema.XmlSchemaValidationFlags.ReportValidationWarnings;

            readerSettings.ValidationEventHandler += new System.Xml.Schema.ValidationEventHandler(OnSchemaValidationEvent); 
            readerSettings.ValidationType = ValidationType.Schema;
 
            XmlSchemaSet schemaSet = SomSchemaSetHelper.GetSchemaSet(DataModel); 

            // Do not use readerSetting.Schemas.Add(schemaSet) 
            // you must use the line below for this to work in
            // a multithread environment
            readerSettings.Schemas = schemaSet;
 
            return readerSettings;
 
        } 

        ///  
        /// Called by the validating reader when the schema is xsd invalid
        /// 
        /// the validating reader
        /// information about the validation error 
        internal void OnSchemaValidationEvent(object sender, System.Xml.Schema.ValidationEventArgs e)
        { 
            Debug.Assert(e != null); 
            XmlReader reader = sender as XmlReader;
            if (reader != null && !IsValidateableXmlNamespace(reader.NamespaceURI, reader.NodeType == XmlNodeType.Attribute)) 
            {
                //For V1 Schemas, we never returned errors for elements in custom namespaces.
                //But the behavior is not totally correct since the error might have occured inside a known namespace
                //even though the element that the reader pointing to is in a custom namespace. But if we fix that, it would 
                //cause lot of breaking changes for V1 customers since we can not change the xsd for them.
                //For attributes, we can ignore the errors always since attributes are unordered and custom attributes should always be allowed. 
                if ((this.SchemaVersion == XmlConstants.EdmVersionForV1) || (this.SchemaVersion == XmlConstants.EdmVersionForV1_1)) 
                {
                    return; 
                }
                // For V2 Schemas that have custom namespaces, the only thing we would not catch are warnings.
                //We also need to ignore any errors reported on custom namespace since they would become annotations.
                Debug.Assert(this.SchemaVersion == XmlConstants.EdmVersionForV2 || SchemaVersion == XmlConstants.UndefinedVersion, "Have you added a new Edm Version?"); 
                if ( (reader.NodeType == XmlNodeType.Attribute) || (e.Severity == System.Xml.Schema.XmlSeverityType.Warning))
                { 
                    return; 
                }
            } 

            //Ignore the warnings for attributes in V2 since we would see warnings for undeclared attributes in empty namespace
            //that are on elements in custom namespace. For undeclared attributes in known namespace, we would see errors.
            if ((this.SchemaVersion == XmlConstants.EdmVersionForV2) && (reader.NodeType == XmlNodeType.Attribute) 
                && (e.Severity == System.Xml.Schema.XmlSeverityType.Warning))
            { 
                return; 
            }
 
            EdmSchemaErrorSeverity severity = EdmSchemaErrorSeverity.Error;
            if (e.Severity == System.Xml.Schema.XmlSeverityType.Warning)
                severity = EdmSchemaErrorSeverity.Warning;
            AddError(ErrorCode.XmlError, severity, e.Exception.LineNumber, e.Exception.LinePosition, e.Message); 

        } 
 

 
        public bool IsParseableXmlNamespace(string xmlNamespaceUri, bool isAttribute)
        {
            if (string.IsNullOrEmpty(xmlNamespaceUri) && isAttribute)
            { 
                // we own the empty namespace for attributes
                return true; 
            } 

            if (_parseableXmlNamespaces == null) 
            {
                _parseableXmlNamespaces = new HashSet();
                foreach (var schemaResource in XmlSchemaResource.GetMetadataSchemaResourceMap(this.SchemaVersion).Values)
                { 
                    _parseableXmlNamespaces.Add(schemaResource.NamespaceUri);
                } 
            } 

            return _parseableXmlNamespaces.Contains(xmlNamespaceUri); 
        }


        HashSet _validatableXmlNamespaces; 
        HashSet _parseableXmlNamespaces;
        public bool IsValidateableXmlNamespace(string xmlNamespaceUri, bool isAttribute) 
        { 
            if (string.IsNullOrEmpty(xmlNamespaceUri) && isAttribute)
            { 
                // we own the empty namespace for attributes
                return true;
            }
 
            if(_validatableXmlNamespaces == null)
            { 
                HashSet validatableXmlNamespaces = new HashSet(); 
                double schemaVersion = SchemaVersion == XmlConstants.UndefinedVersion ? XmlConstants.SchemaVersionLatest : SchemaVersion;
                foreach (var schemaResource in XmlSchemaResource.GetMetadataSchemaResourceMap(schemaVersion).Values) 
                {
                    AddAllSchemaResourceNamespaceNames(validatableXmlNamespaces, schemaResource);
                }
 
                if (SchemaVersion == XmlConstants.UndefinedVersion)
                { 
                    // we are getting called before the version is set 
                    return validatableXmlNamespaces.Contains(xmlNamespaceUri);
                } 
                _validatableXmlNamespaces = validatableXmlNamespaces;
            }

            return _validatableXmlNamespaces.Contains(xmlNamespaceUri); 
        }
 
        private static void AddAllSchemaResourceNamespaceNames(HashSet hashSet, XmlSchemaResource schemaResource) 
        {
            hashSet.Add(schemaResource.NamespaceUri); 
            foreach(var import in schemaResource.ImportedSchemas)
            {
                AddAllSchemaResourceNamespaceNames(hashSet, import);
            } 
        }
 
 

        internal override void ResolveTopLevelNames() 
        {
            base.ResolveTopLevelNames();

            // Resolve all the referenced namespace to make sure that this namespace is valid 
            AliasResolver.ResolveNamespaces();
 
            foreach (SchemaElement element in SchemaTypes) 
            {
                element.ResolveTopLevelNames(); 
            }

            foreach (Function function in Functions)
            { 
                function.ResolveTopLevelNames();
            } 
        } 

        internal override void ResolveSecondLevelNames() 
        {
            base.ResolveSecondLevelNames();
            foreach (SchemaElement element in SchemaTypes)
            { 
                element.ResolveSecondLevelNames();
            } 
 
            foreach (Function function in Functions)
            { 
                function.ResolveSecondLevelNames();
            }
        }
 
        /// 
        /// Vaidate the schema. 
        ///  
        /// list of errors
        internal override void Validate() 
        {
            // Also check for alias to be system namespace
            if (!String.IsNullOrEmpty(Alias) && EdmItemCollection.IsSystemNamespace(ProviderManifest, Alias))
            { 
                AddError(ErrorCode.CannotUseSystemNamespaceAsAlias, EdmSchemaErrorSeverity.Error,
                    System.Data.Entity.Strings.CannotUseSystemNamespaceAsAlias(Alias)); 
            } 

            // Check whether the schema namespace is a system namespace. We set the provider manifest to edm provider manifest 
            // if we need to check for system namespace. Otherwise, it will be set to null (if we are loading edm provider manifest)
            if (ProviderManifest != null &&
                EdmItemCollection.IsSystemNamespace(ProviderManifest, Namespace))
            { 
                AddError(ErrorCode.SystemNamespace, EdmSchemaErrorSeverity.Error, System.Data.Entity.Strings.SystemNamespaceEncountered(Namespace));
            } 
 

            foreach (SchemaElement schemaType in this.SchemaTypes) 
            {
                schemaType.Validate();
            }
 
            foreach (Function function in this.Functions)
            { 
                AddFunctionType(function); 
                function.Validate();
            } 
        }

        #endregion
 
        #region Public Properties
 
        ///  
        /// The namespaceUri of the winfs xml namespace
        ///  
        internal string SchemaXmlNamespace
        {
            get
            { 
                return _schemaXmlNamespace;
            } 
            private set 
            {
                _schemaXmlNamespace = value; 
            }
        }

        internal DbProviderManifest ProviderManifest 
        {
            get 
            { 
                return _schemaManager.GetProviderManifest((string message, ErrorCode code, EdmSchemaErrorSeverity severity)=>AddError(code, severity, message));
            } 
        }

        /// 
        /// Version of the EDM that this schema represents. 
        /// 
        internal double SchemaVersion 
        { 
            get
            { 
                return _schemaVersion;
            }
            set
            { 
                _schemaVersion = value;
            } 
        } 

        ///  
        /// Alias for the schema (null if none)
        /// 
        internal virtual string Alias
        { 
            get
            { 
                return _alias; 
            }
            private set 
            {
                _alias = value;
            }
        } 
        /// 
        /// Namespace of the schema 
        ///  
        internal virtual string Namespace
        { 
            get
            {
                return _namespaceName;
            } 
            private set
            { 
                _namespaceName = value; 
            }
        } 

        // ISSUE: jthunter-03/14/05 - The [....] "schemas" don't follow the ".Store" assembly
        // naming convention but need to have the right StoreNamespace reported.
        // 
        private static readonly string[] ClientNamespaceOfSchemasMissingStoreSuffix =
        { 
            "System.Storage.[....].Utility", 
            "System.Storage.[....].Services"
        }; 

        /// 
        /// Uri containing the file that defines the schema
        ///  
        internal string Location
        { 
            get 
            {
                return _location; 
            }
            private set
            {
                _location = value; 
            }
        } 
 
        private MetadataProperty _schemaSourceProperty;
        internal MetadataProperty SchemaSource 
        {
            get
            {
                if (_schemaSourceProperty == null) 
                {
                    // create the System MetadataProperty for the SchemaSource 
                    _schemaSourceProperty = new MetadataProperty("SchemaSource", 
                                        EdmProviderManifest.Instance.GetPrimitiveType(PrimitiveTypeKind.String),
                                        false, // IsCollection 
                                        _location != null ? _location : string.Empty);
                }

                return _schemaSourceProperty; 
            }
        } 
 
        /// 
        /// List of all types defined in the schema 
        /// 
        internal List SchemaTypes
        {
            get 
            {
                if (_schemaTypes == null) 
                { 
                    _schemaTypes = new List();
                } 
                return _schemaTypes;
            }
        }
 
        /// 
        /// Fully qualified name of the schema (same as the namespace name) 
        ///  
        public override string FQName
        { 
            get
            {
                return Namespace;
            } 
        }
        private List Functions 
        { 
            get
            { 
                if (_functions == null)
                {
                    _functions = new List();
                } 
                return _functions;
            } 
        } 

        #endregion 

        #region Protected Properties
        protected override bool HandleElement(XmlReader reader)
        { 
            if (base.HandleElement(reader))
            { 
                return true; 
            }
            else if (CanHandleElement(reader, XmlConstants.EntityType)) 
            {
                HandleEntityTypeElement(reader);
                return true;
            } 
            else if (CanHandleElement(reader, XmlConstants.ComplexType))
            { 
                HandleInlineTypeElement(reader); 
                return true;
            } 
            else if (CanHandleElement(reader, XmlConstants.Association))
            {
                HandleAssociationElement(reader);
                return true; 
            }
 
            // Using is only supported in EntityDataModel 
            if (DataModel == SchemaDataModelOption.EntityDataModel)
            { 
                if (CanHandleElement(reader, XmlConstants.Using))
                {
                    HandleUsingElement(reader);
                    return true; 
                }
                else if (CanHandleElement(reader, XmlConstants.Function)) 
                { 
                    HandleModelFunctionElement(reader);
                    return true; 
                }

            }
 
            if (DataModel == SchemaDataModelOption.EntityDataModel ||
                DataModel == SchemaDataModelOption.ProviderDataModel) 
            { 
                if (CanHandleElement(reader, XmlConstants.EntityContainer))
                { 
                    HandleEntityContainerTypeElement(reader);
                    return true;
                }
                else if (DataModel == SchemaDataModelOption.ProviderDataModel) 
                {
                    if (CanHandleElement(reader, XmlConstants.Function)) 
                    { 
                        HandleFunctionElement(reader);
                        return true; 
                    }
                }
            }
            else 
            {
                Debug.Assert(DataModel == SchemaDataModelOption.ProviderManifestModel, "Did you add a new option?"); 
                if (CanHandleElement(reader, XmlConstants.TypesElement)) 
                {
                    SkipThroughElement(reader); 
                    return true;
                }
                else if (CanHandleElement(reader, XmlConstants.FunctionsElement))
                { 
                    SkipThroughElement(reader);
                    return true; 
                } 
                else if (CanHandleElement(reader, XmlConstants.Function))
                { 
                    HandleFunctionElement(reader);
                    return true;
                }
                else if (CanHandleElement(reader, XmlConstants.TypeElement)) 
                {
                    HandleTypeInformationElement(reader); 
                    return true; 
                }
            } 

            return false;
        }
 
        protected override bool ProhibitAttribute(string namespaceUri, string localName)
        { 
            if (base.ProhibitAttribute(namespaceUri, localName)) 
            {
                return true; 
            }

            if (namespaceUri == null && localName == XmlConstants.Name)
            { 
                return false;
            } 
            return false; 
        }
 
        protected override bool HandleAttribute(XmlReader reader)
        {
            Debug.Assert(_depth > 0);
            if (_depth == 1) 
            {
                return false; 
            } 
            else
            { 
                if (base.HandleAttribute(reader))
                {
                    return true;
                } 
                else if (CanHandleAttribute(reader, XmlConstants.Alias))
                { 
                    HandleAliasAttribute(reader); 
                    return true;
                } 
                else if (CanHandleAttribute(reader, XmlConstants.Namespace))
                {
                    HandleNamespaceAttribute(reader);
                    return true; 
                }
                else if (CanHandleAttribute(reader, XmlConstants.Provider)) 
                { 
                    HandleProviderAttribute(reader);
                    return true; 
                }
                else if (CanHandleAttribute(reader, XmlConstants.ProviderManifestToken))
                {
                    HandleProviderManifestTokenAttribute(reader); 
                    return true;
                } 
            } 
            return false;
        } 

        #endregion

        #region Internal Methods 
        /// 
        /// Called when all attributes for the schema element have been handled 
        ///  
        protected override void HandleAttributesComplete()
        { 

            if (_depth < RootDepth)
            {
                return; 
            }
            else if (_depth == RootDepth) 
            { 
                // only call when done with the root element
                _schemaManager.EnsurePrimitiveSchemaIsLoaded(); 
            }

            base.HandleAttributesComplete();
        } 

        protected override void SkipThroughElement(XmlReader reader) 
        { 
            try
            { 
                _depth++;
                base.SkipThroughElement(reader);
            }
            finally 
            {
                _depth--; 
            } 
        }
 
        /// 
        /// Look up a fully qualified type name reference.
        /// 
        /// element containing the reference 
        /// the fully qualified type name
        /// the referenced schema type 
        /// false if there was an error 
        internal bool ResolveTypeName(SchemaElement usingElement, string typeName, out SchemaType type)
        { 
            Debug.Assert(usingElement != null);
            Debug.Assert(typeName != null);

            type = null; 

            // get the schema(s) that match the namespace/alias 
            string actualQualification; 
            string unqualifiedTypeName;
            Utils.ExtractNamespaceAndName(DataModel, typeName, out actualQualification, out unqualifiedTypeName); 
            string definingQualification = actualQualification;

            if (definingQualification == null)
            { 
                definingQualification = this.ProviderManifest == null ? this._namespaceName : this.ProviderManifest.NamespaceName;
            } 
 
            string namespaceName;
            // First check if there is an alias defined by this name. For primitive type namespace, we do not need to resolve 
            // any alias, since that's a reserved keyword and we don't allow alias with that name
            if (actualQualification == null || !AliasResolver.TryResolveAlias(definingQualification, out namespaceName))
            {
                namespaceName = definingQualification; 
            }
 
            // Resolve the type name 
            if (!SchemaManager.TryResolveType(namespaceName, unqualifiedTypeName, out type))
            { 
                // it must be an undefined type.
                if (actualQualification == null)
                {
                    // Every type except the primitive type must be qualified 
                    usingElement.AddError(ErrorCode.NotInNamespace, EdmSchemaErrorSeverity.Error, System.Data.Entity.Strings.NotNamespaceQualified(typeName));
                } 
                else if (!SchemaManager.IsValidNamespaceName(namespaceName)) 
                {
                    usingElement.AddError(ErrorCode.BadNamespace, EdmSchemaErrorSeverity.Error, System.Data.Entity.Strings.BadNamespaceOrAlias(actualQualification)); 
                }
                else
                {
                    // if the type name was alias qualified 
                    if (namespaceName != definingQualification)
                    { 
                        usingElement.AddError(ErrorCode.NotInNamespace, EdmSchemaErrorSeverity.Error, System.Data.Entity.Strings.NotInNamespaceAlias(unqualifiedTypeName, namespaceName, definingQualification)); 
                    }
                    else 
                    {
                        usingElement.AddError(ErrorCode.NotInNamespace, EdmSchemaErrorSeverity.Error, System.Data.Entity.Strings.NotInNamespaceNoAlias(unqualifiedTypeName, namespaceName));
                    }
                } 
                return false;
            } 
            // For ssdl and provider manifest, make sure that the type is present in this schema or primitive schema 
            else if (this.DataModel != SchemaDataModelOption.EntityDataModel && type.Schema != this && type.Schema != this.SchemaManager.PrimitiveSchema)
            { 
                Debug.Assert(type.Namespace != this.Namespace, "Using element is not allowed in the schema of ssdl and provider manifest");
                usingElement.AddError(ErrorCode.InvalidNamespaceOrAliasSpecified, EdmSchemaErrorSeverity.Error, System.Data.Entity.Strings.InvalidNamespaceOrAliasSpecified(actualQualification));
                return false;
            } 

            return true; 
        } 
        #endregion
 
        #region Internal Properties
        /// 
        /// List containing the current schema and all referenced schemas. Used for alias and namespace lookup.
        ///  
        internal AliasResolver AliasResolver
        { 
            get 
            {
                if (_aliasResolver == null) 
                {
                    _aliasResolver = new AliasResolver(this);
                }
 
                return _aliasResolver;
            } 
        } 

        ///  
        /// The schema data model
        /// 
        internal SchemaDataModelOption DataModel
        { 
            get
            { 
                return SchemaManager.DataModel; 
            }
        } 

        /// 
        /// The schema data model
        ///  
        internal SchemaManager SchemaManager
        { 
            get 
            {
                return _schemaManager; 
            }
        }

        #endregion 

        #region Private Methods 
        ///  
        /// Handler for the Namespace attribute
        ///  
        /// xml reader currently positioned at Namespace attribute
        private void HandleNamespaceAttribute(XmlReader reader)
        {
            Debug.Assert(reader != null); 

            ReturnValue returnValue = HandleDottedNameAttribute(reader, Namespace, null); 
            if (!returnValue.Succeeded) 
                return;
 
            Namespace = returnValue.Value;
        }

        ///  
        /// Handler for the Alias attribute
        ///  
        /// xml reader currently positioned at Alias attribute 
        private void HandleAliasAttribute(XmlReader reader)
        { 
            Debug.Assert(reader != null);

            Alias = HandleUndottedNameAttribute(reader, Alias);
 
        }
 
        ///  
        /// Handler for the Provider attribute
        ///  
        /// xml reader currently positioned at Provider attribute
        private void HandleProviderAttribute(XmlReader reader)
        {
            Debug.Assert(reader != null); 

            string provider = reader.Value; 
            _schemaManager.ProviderNotification(provider, 
                (string message, ErrorCode code, EdmSchemaErrorSeverity severity) => AddError(code, severity, reader, message));
        } 

        /// 
        /// Handler for the ProviderManifestToken attribute
        ///  
        /// xml reader currently positioned at ProviderManifestToken attribute
        private void HandleProviderManifestTokenAttribute(XmlReader reader) 
        { 
            Debug.Assert(reader != null);
 
            string providerManifestToken = reader.Value;
            _schemaManager.ProviderManifestTokenNotification(providerManifestToken,
                (string message, ErrorCode code, EdmSchemaErrorSeverity severity) => AddError(code, severity, reader, message));
        } 

        ///  
        /// Handler for the using element 
        /// 
        ///  
        private void HandleUsingElement(XmlReader reader)
        {
            UsingElement referencedNamespace = new UsingElement(this);
            referencedNamespace.Parse(reader); 
            AliasResolver.Add(referencedNamespace);
        } 
 
        /// 
        /// Handler for the top level element 
        /// 
        /// xml reader currently positioned at top level element
        private void HandleTopLevelSchemaElement(XmlReader reader)
        { 
            Debug.Assert(reader != null);
 
            try 
            {
                _depth += RootDepth; 
                Parse(reader);
            }
            finally
            { 
                _depth -= RootDepth;
            } 
        } 

 
        /// 
        /// Handler for the EntityType element
        /// 
        /// xml reader currently positioned at EntityType element 
        private void HandleEntityTypeElement(XmlReader reader)
        { 
            Debug.Assert(reader != null); 

            SchemaEntityType itemType = new SchemaEntityType(this); 

            itemType.Parse(reader);

            TryAddType(itemType, true/*doNotAddErrorForEmptyName*/); 
        }
 
        ///  
        /// Handler for the TypeInformation element
        ///  
        /// xml reader currently positioned at EntityType element
        private void HandleTypeInformationElement(XmlReader reader)
        {
            Debug.Assert(reader != null); 

            TypeElement type = new TypeElement(this); 
 
            type.Parse(reader);
 
            TryAddType(type, true/*doNotAddErrorForEmptyName*/);
        }

        ///  
        /// Handler for the Function element
        ///  
        /// xml reader currently positioned at EntityType element 
        private void HandleFunctionElement(XmlReader reader)
        { 
            Debug.Assert(reader != null);

            Function function = new Function(this);
 
            function.Parse(reader);
 
            this.Functions.Add(function); 
        }
 

        private void HandleModelFunctionElement(XmlReader reader)
        {
            Debug.Assert(reader != null); 

            ModelFunction function = new ModelFunction(this); 
 
            function.Parse(reader);
 
            this.Functions.Add(function);
        }

        ///  
        /// Handler for the Association element
        ///  
        /// xml reader currently positioned at Association element 
        private void HandleAssociationElement(XmlReader reader)
        { 
            Debug.Assert(reader != null);

            Relationship relationship = new Relationship(this, RelationshipKind.Association);
 
            relationship.Parse(reader);
 
            TryAddType(relationship, true/*doNotAddErrorForEmptyName*/); 
        }
        ///  
        /// Handler for the InlineType element
        /// 
        /// xml reader currently positioned at InlineType element
        private void HandleInlineTypeElement(XmlReader reader) 
        {
            Debug.Assert(reader != null); 
 
            SchemaComplexType complexType = new SchemaComplexType(this);
 
            complexType.Parse(reader);

            TryAddType(complexType, true/*doNotAddErrorForEmptyName*/);
        } 

        ///  
        /// Handler for the EntityContainer element 
        /// 
        /// xml reader currently positioned at EntityContainer element 
        private void HandleEntityContainerTypeElement(XmlReader reader)
        {
            Debug.Assert(reader != null);
 
            EntityContainer type = new EntityContainer(this);
            type.Parse(reader); 
            TryAddContainer(type, true/*doNotAddErrorForEmptyName*/); 
        }
 
        /// 
        /// reset the error collection
        /// 
        /// old error list 
        private List ResetErrors()
        { 
            List errors = _errors; 
            _errors = new List();
 
            return errors;
        }

        protected void TryAddType(SchemaType schemaType, bool doNotAddErrorForEmptyName) 
        {
            this.SchemaManager.SchemaTypes.Add(schemaType, doNotAddErrorForEmptyName, 
                Strings.TypeNameAlreadyDefinedDuplicate); 
            this.SchemaTypes.Add(schemaType);
        } 

        protected void TryAddContainer(SchemaType schemaType, bool doNotAddErrorForEmptyName)
        {
            this.SchemaManager.SchemaTypes.Add(schemaType, doNotAddErrorForEmptyName, 
                Strings.EntityContainerAlreadyExists);
            this.SchemaTypes.Add(schemaType); 
        } 

        protected void AddFunctionType(Function function) 
        {
            string space = DataModel == SchemaDataModelOption.EntityDataModel ? "Conceptual" : "Storage";

            if (this.SchemaVersion >= XmlConstants.EdmVersionForV2 && this.SchemaManager.SchemaTypes.ContainsKey(function.FQName)) 
            {
                function.AddError(ErrorCode.AlreadyDefined, EdmSchemaErrorSeverity.Error, 
                    System.Data.Entity.Strings.AmbiguousFunctionAndType(function.FQName, space)); 
            }
            else 
            {
                AddErrorKind error = this.SchemaManager.SchemaTypes.TryAdd(function);
                Debug.Assert(error != AddErrorKind.MissingNameError, "Function identity can never be null while adding global functions");
 
                if (error != AddErrorKind.Succeeded)
                { 
                    function.AddError(ErrorCode.AlreadyDefined, EdmSchemaErrorSeverity.Error, 
                        System.Data.Entity.Strings.AmbiguousFunctionOverload(function.FQName, space));
                } 
                else
                {
                    this.SchemaTypes.Add(function);
                } 
            }
        } 
 
        #endregion
 
        #region Private Properties


        #endregion 

 
        private static class SomSchemaSetHelper 
        {
            private static Memoizer _cachedSchemaSets = 
                new Memoizer(ComputeSchemaSet, EqualityComparer.Default);

            internal static List GetPrimarySchemaNamespaces(SchemaDataModelOption dataModel)
            { 
                List namespaces = new List();
                if (dataModel == SchemaDataModelOption.EntityDataModel) 
                { 
                    namespaces.Add(XmlConstants.ModelNamespace_1);
                    namespaces.Add(XmlConstants.ModelNamespace_1_1); 
                    namespaces.Add(XmlConstants.ModelNamespace_2);
                }
                else if (dataModel == SchemaDataModelOption.ProviderDataModel)
                { 
                    namespaces.Add(XmlConstants.TargetNamespace_1);
                    namespaces.Add(XmlConstants.TargetNamespace_2); 
                } 
                else
                { 
                    Debug.Assert(dataModel == SchemaDataModelOption.ProviderManifestModel, "Unknown SchemaDataModelOption did you add one?");
                    namespaces.Add(XmlConstants.ProviderManifestNamespace);
                }
                return namespaces; 
            }
 
            internal static XmlSchemaSet GetSchemaSet(SchemaDataModelOption dataModel) 
            {
                return _cachedSchemaSets.Evaluate(dataModel); 
            }

            private static XmlSchemaSet ComputeSchemaSet(SchemaDataModelOption dataModel)
            { 
                List namespaceNames = GetPrimarySchemaNamespaces(dataModel);
                Debug.Assert(namespaceNames.Count > 0, "Unknown Datamodel"); 
 
                XmlSchemaSet schemaSet = new XmlSchemaSet();
                // remove the default XmlResolver which will look on 
                // disk for the referenced schemas that we already provided
                schemaSet.XmlResolver = null;
                var schemaResourceMap = XmlSchemaResource.GetMetadataSchemaResourceMap(XmlConstants.SchemaVersionLatest);
                HashSet schemasAlreadyAdded = new HashSet(); 
                foreach (string namespaceName in namespaceNames)
                { 
                    Debug.Assert(schemaResourceMap.ContainsKey(namespaceName), "the namespace name is not one we have a schema set for"); 
                    XmlSchemaResource schemaResource = schemaResourceMap[namespaceName];
                    AddXmlSchemaToSet(schemaSet, schemaResource, schemasAlreadyAdded); 
                }
                schemaSet.Compile();

                return schemaSet; 
            }
 
            private static void AddXmlSchemaToSet(XmlSchemaSet schemaSet, XmlSchemaResource schemaResource, HashSet schemasAlreadyAdded) 
            {
                // loop through the children to do a depth first load 
                foreach (var import in schemaResource.ImportedSchemas)
                {
                    AddXmlSchemaToSet(schemaSet, import, schemasAlreadyAdded);
                } 

                if (!schemasAlreadyAdded.Contains(schemaResource.NamespaceUri)) 
                { 
                    Stream xsdStream = GetResourceStream(schemaResource.ResourceName);
                    XmlSchema schema = XmlSchema.Read(xsdStream, null); 
                    schemaSet.Add(schema);
                    schemasAlreadyAdded.Add(schemaResource.NamespaceUri);
                }
            } 

            private static Stream GetResourceStream(string resourceName) 
            { 
                Debug.Assert(resourceName != null, "resourceName cannot be null");
 
                Stream resourceStream = null;
                System.Reflection.Assembly executingAssembly = System.Reflection.Assembly.GetExecutingAssembly();
                if (executingAssembly != null)
                { 
                    resourceStream = executingAssembly.GetManifestResourceStream(resourceName);
                } 
 
                Debug.Assert(resourceStream != null, string.Format(CultureInfo.CurrentCulture, "Unable to load the resource {0} from assembly resources.", resourceName));
 
                return resourceStream;
            }
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK