SchemaElement.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / Orcas / QFE / ndp / fx / src / DataEntity / System / Data / EntityModel / SchemaObjectModel / SchemaElement.cs / 2 / SchemaElement.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.Diagnostics; 
using System.Xml;
using System.Data; 
using System.Data.Metadata.Edm; 
using System.Reflection;
using System.Data.Entity; 



namespace System.Data.EntityModel.SchemaObjectModel 
{
    ///  
    /// Summary description for SchemaElement. 
    /// 
    [DebuggerDisplay("Name={Name}")] 
    internal abstract class SchemaElement
    {
        // see http://www.w3.org/TR/2006/REC-xml-names-20060816/
        internal const string XmlNamespaceNamespace = "http://www.w3.org/2000/xmlns/"; 

 
        #region Instance Fields 
        private SchemaElement _parentElement = null;
        private Schema _schema = null; 
        private int _lineNumber = 0;
        private int _linePosition = 0;
        private string _name = null;
        private DocumentationElement _documentation = null; 

        private List _otherContent; 
 
        #endregion
 
        #region Static Fields
        /// 
        protected const int MaxValueVersionComponent = short.MaxValue;
        #endregion 

        #region Public Properties 
        ///  
        ///
        ///  
        internal  int LineNumber
        {
            get
            { 
                return _lineNumber;
            } 
        } 

        ///  
        ///
        /// 
        internal  int LinePosition
        { 
            get
            { 
                return _linePosition; 
            }
        } 

        /// 
        ///
        ///  
        public virtual string Name
        { 
            get 
            {
                return _name; 
            }
            set
            {
                _name = value; 
            }
        } 
 
        /// 
        /// 
        /// 
        internal  DocumentationElement Documentation
        {
            get 
            {
                return _documentation; 
            } 
            set
            { 
                _documentation = value;
            }
        }
 
        /// 
        /// 
        ///  
        internal  SchemaElement ParentElement
        { 
            get
            {
                return _parentElement;
            } 
            private set
            { 
                _parentElement = value; 
            }
        } 

        /// 
        ///
        ///  
        internal Schema Schema
        { 
            get 
            {
                return _schema; 
            }
            set
            {
                _schema = value; 
            }
        } 
 
        /// 
        /// 
        /// 
        public  virtual string FQName
        {
            get 
            {
                return Name; 
            } 
        }
 
        /// 
        ///
        /// 
        public virtual string Identity 
        {
            get 
            { 
                return Name;
            } 
        }


        public List OtherContent 
        {
            get 
            { 
                if (_otherContent == null)
                { 
                    _otherContent = new List();
                }

                return _otherContent; 
            }
        } 
        #endregion 

        #region Internal Methods 
        /// 
        /// Validates this element and its children
        /// 
 
        internal virtual void Validate()
        { 
        } 

        ///  
        ///
        /// 
        internal void AddAlreadyDefinedError(XmlReader reader)
        { 
            AddError( ErrorCode.AlreadyDefined, EdmSchemaErrorSeverity.Error, reader, System.Data.Entity.Strings.AlreadyDefined(reader.Name ) );
        } 
 
        /// 
        /// 
        /// 
        /// 
        /// 
        ///  
        /// 
        ///  
        internal void AddError( ErrorCode errorCode, EdmSchemaErrorSeverity severity, int lineNumber, int linePosition, object message ) 
        {
            AddError(errorCode,severity,SchemaLocation,lineNumber,linePosition,message); 
        }

        /// 
        /// 
        /// 
        ///  
        ///  
        /// 
        ///  
        internal void AddError( ErrorCode errorCode, EdmSchemaErrorSeverity severity, XmlReader reader, object message )
        {
            int lineNumber;
            int linePosition; 
            GetPositionInfo(reader, out lineNumber, out linePosition);
            AddError(errorCode,severity,SchemaLocation,lineNumber,linePosition,message); 
        } 

        ///  
        ///
        /// 
        /// 
        ///  
        /// 
        internal void AddError( ErrorCode errorCode, EdmSchemaErrorSeverity severity, object message ) 
        { 
            AddError(errorCode,severity,SchemaLocation,LineNumber,LinePosition,message);
        } 

        /// 
        ///
        ///  
        /// 
        ///  
        ///  
        /// 
        internal void AddError( ErrorCode errorCode, EdmSchemaErrorSeverity severity, SchemaElement element, object message ) 
        {
            AddError(errorCode,severity,element.Schema.Location,element.LineNumber,element.LinePosition,message);
        }
 
        /// 
        /// 
        ///  
        /// 
        ///  
        internal void Parse(XmlReader reader)
        {
            GetPositionInfo(reader);
 
            bool hasEndElement = !reader.IsEmptyElement;
 
            Debug.Assert(reader.NodeType == XmlNodeType.Element); 
            for ( bool more = reader.MoveToFirstAttribute(); more; more = reader.MoveToNextAttribute() )
            { 
                ParseAttribute(reader);
            }
            HandleAttributesComplete();
 
            bool done = !hasEndElement;
            bool skipToNextElement = false; 
            while ( !done ) 
            {
                if ( skipToNextElement ) 
                {
                    skipToNextElement = false;
                    reader.Skip();
                    if ( reader.EOF ) 
                        break;
                } 
                else 
                {
                    if ( !reader.Read() ) 
                        break;
                }
                switch ( reader.NodeType )
                { 
                    case XmlNodeType.Element:
                        skipToNextElement = ParseElement(reader); 
                        break; 

                    case XmlNodeType.EndElement: 
                    {
                        done = true;
                        break;
                    } 

                    case XmlNodeType.CDATA: 
                    case XmlNodeType.Text: 
                    case XmlNodeType.SignificantWhitespace:
                        ParseText(reader); 
                        break;

                        // we ignore these childless elements
                    case XmlNodeType.Whitespace: 
                    case XmlNodeType.XmlDeclaration:
                    case XmlNodeType.Comment: 
                    case XmlNodeType.Notation: 
                    case XmlNodeType.ProcessingInstruction:
                    { 
                        break;
                    }

                        // we ignore these elements that can have children 
                    case XmlNodeType.DocumentType:
                    case XmlNodeType.EntityReference: 
                    { 
                        skipToNextElement = true;
                        break; 
                    }

                    default:
                    { 
                        AddError( ErrorCode.UnexpectedXmlNodeType, EdmSchemaErrorSeverity.Error, reader,
                            System.Data.Entity.Strings.UnexpectedXmlNodeType(reader.NodeType)); 
                        skipToNextElement = true; 
                        break;
                    } 
                }
            }
            HandleChildElementsComplete();
            if ( reader.EOF && reader.Depth > 0 ) 
            {
                AddError( ErrorCode.MalformedXml, EdmSchemaErrorSeverity.Error, 0, 0, 
                    System.Data.Entity.Strings.MalformedXml(LineNumber,LinePosition)); 
            }
        } 

        /// 
        /// Set the current line number and position for an XmlReader
        ///  
        /// the reader whose position is desired
        internal void GetPositionInfo(XmlReader reader) 
        { 
            GetPositionInfo(reader,out _lineNumber,out _linePosition);
        } 

        /// 
        /// Get the current line number and position for an XmlReader
        ///  
        /// the reader whose position is desired
        /// the line number 
        /// the line position 
        internal static void GetPositionInfo(XmlReader reader, out int lineNumber, out int linePosition)
        { 
            IXmlLineInfo xmlLineInfo = reader as IXmlLineInfo;
            if ( xmlLineInfo != null && xmlLineInfo.HasLineInfo() )
            {
                lineNumber = xmlLineInfo.LineNumber; 
                linePosition = xmlLineInfo.LinePosition;
            } 
            else 
            {
                lineNumber = 0; 
                linePosition = 0;
            }
        }
 
        /// 
        /// 
        ///  
        internal virtual void ResolveTopLevelNames()
        { 
        }
        internal virtual void ResolveSecondLevelNames()
        {
        } 
        #endregion
 
        #region Protected Methods 

        ///  
        ///
        /// 
        /// 
        internal SchemaElement(SchemaElement parentElement) 
        {
            if ( parentElement != null ) 
            { 
                ParentElement = parentElement;
                for ( SchemaElement element = parentElement; element != null; element = element.ParentElement ) 
                {
                    Schema schema = element as Schema;
                    if ( schema != null )
                    { 
                        Schema = schema;
                        break; 
                    } 
                }
 
                if (Schema == null)
                {
                    throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.AllElementsMustBeInSchema);
                } 
            }
        } 
 
        internal SchemaElement(SchemaElement parentElement, string name)
            : this(parentElement) 
        {
            _name = name;
        }
 
        /// 
        /// 
        ///  
        protected virtual void HandleAttributesComplete()
        { 
        }

        /// 
        /// 
        /// 
        protected virtual void HandleChildElementsComplete() 
        { 
        }
 
        /// 
        ///
        /// 
        ///  
        /// 
        ///  
        protected string HandleUndottedNameAttribute(XmlReader reader, string field) 
        {
            string name = field; 
            if ( !string.IsNullOrEmpty(field) )
            {
                AddAlreadyDefinedError(reader);
                return name; 
            }
 
            bool success = Utils.GetUndottedName(Schema, reader, out name); 
            if ( !success )
                return name; 

            return name;
        }
 
        /// 
        /// 
        ///  
        /// 
        ///  
        /// 
        /// 
        protected ReturnValue HandleDottedNameAttribute(XmlReader reader, string field, Func errorFormat)
        { 
            ReturnValue returnValue = new ReturnValue();
            if ( !string.IsNullOrEmpty(field) ) 
            { 
                AddError( ErrorCode.AlreadyDefined, EdmSchemaErrorSeverity.Error, reader, errorFormat(reader.Name) );
                return returnValue; 
            }

            string value;
            if ( !Utils.GetDottedName(Schema,reader,out value) ) 
                return returnValue;
 
            returnValue.Value = value; 
            return returnValue;
        } 

        /// 
        /// Use to handle an attribute with an int data type
        ///  
        /// the reader positioned at the int attribute
        /// The int field to be given the value found 
        /// true if an int value was successfuly extracted from the attribute, false otherwise. 
        internal bool HandleIntAttribute(XmlReader reader, ref int field)
        { 
            int value;
            if ( !Utils.GetInt(Schema, reader, out value) )
                return false;
 
            field = value;
            return true; 
        } 

        ///  
        /// Use to handle an attribute with an int data type
        /// 
        /// the reader positioned at the int attribute
        /// The int field to be given the value found 
        /// true if an int value was successfuly extracted from the attribute, false otherwise.
        internal bool HandleByteAttribute(XmlReader reader, ref byte field) 
        { 
            byte value;
            if ( !Utils.GetByte(Schema, reader, out value) ) 
                return false;

            field = value;
            return true; 
        }
        ///  
        /// 
        /// 
        ///  
        /// 
        /// 
        internal bool HandleBoolAttribute(XmlReader reader,ref bool field)
        { 
            bool value;
            if ( !Utils.GetBool(Schema,reader,out value) ) 
                return false; 

            field = value; 
            return true;
        }

        ///  
        /// Use this to jump through an element that doesn't need any processing
        ///  
        /// xml reader currently positioned at an element 
        protected virtual void SkipThroughElement(XmlReader reader)
        { 
            Debug.Assert(reader != null);
            Parse(reader);
        }
 
        #endregion
 
        #region Protected Properties 
        /// 
        /// 
        /// 
        protected string SchemaLocation
        {
            get 
            {
                if ( Schema != null ) 
                    return Schema.Location; 
                return null;
            } 
        }

        protected virtual bool HandleText(XmlReader reader)
        { 
            return false;
        } 
 
        internal virtual SchemaElement Clone(SchemaElement parentElement)
        { 
            throw Error.NotImplemented();
        }
        #endregion
 
        #region Private Methods
        ///  
        /// 
        /// 
        ///  
        /// 
        private void HandleDocumentationElement(XmlReader reader)
        {
            if ( Documentation != null ) 
                AddAlreadyDefinedError(reader);
 
            Documentation = new DocumentationElement(this); 
            Documentation.Parse(reader);
        } 

        /// 
        ///
        ///  
        /// 
        protected virtual void HandleNameAttribute(XmlReader reader) 
        { 
            Name = HandleUndottedNameAttribute(reader, Name);
        } 

        /// 
        ///
        ///  
        /// 
        ///  
        ///  
        /// 
        ///  
        /// 
        private void AddError( ErrorCode errorCode, EdmSchemaErrorSeverity severity, string sourceLocation, int lineNumber, int linePosition, object message )
        {
            EdmSchemaError error = null; 
            string messageString = message as string;
            if ( messageString != null ) 
                error = new EdmSchemaError( messageString, (int)errorCode, severity, sourceLocation, lineNumber, linePosition ); 
            else
            { 
                Exception ex = message as Exception;
                if ( ex != null )
                    error = new EdmSchemaError( ex.Message, (int)errorCode, severity, sourceLocation, lineNumber, linePosition, ex );
                else 
                    error = new EdmSchemaError( message.ToString(), (int)errorCode, severity, sourceLocation, lineNumber, linePosition );
            } 
            Schema.AddError(error); 
        }
 
        /// 
        /// Call handler for the current attribute
        /// 
        /// XmlReader positioned at the attribute 
        private void ParseAttribute(XmlReader reader)
        { 
#if false 
            // the attribute value is schema invalid, just skip it; this avoids some duplicate errors at the expense of better error messages...
            if ( reader.SchemaInfo != null && reader.SchemaInfo.Validity == System.Xml.Schema.XmlSchemaValidity.Invalid ) 
                continue;
#endif
            string attributeNamespace = reader.NamespaceURI;
            if (!Schema.IsParseableXmlNamespace(attributeNamespace, true)) 
            {
                AddOtherContent(reader); 
            } 
            else if (!ProhibitAttribute(attributeNamespace, reader.LocalName)&&
                     HandleAttribute(reader)) 
            {
                return;
            }
            else if (reader.SchemaInfo == null || reader.SchemaInfo.Validity != System.Xml.Schema.XmlSchemaValidity.Invalid) 
            {
                // there's no handler for (namespace,name) and there wasn't a validation error. 
                // Report an error of our own if the node is in no namespace or if it is in one of our xml schemas tartget namespace. 
                if (string.IsNullOrEmpty(attributeNamespace) || Schema.IsParseableXmlNamespace(attributeNamespace, true))
                { 
                    AddError(ErrorCode.UnexpectedXmlAttribute, EdmSchemaErrorSeverity.Error, reader, System.Data.Entity.Strings.UnexpectedXmlAttribute(reader.Name));
                }
            }
        } 

        protected virtual bool ProhibitAttribute(string namespaceUri, string localName) 
        { 
            return false;
        } 


        /// 
        /// This overload assumes the default namespace 
        /// 
        ///  
        ///  
        /// 
        internal static bool CanHandleAttribute(XmlReader reader, string localName) 
        {
            Debug.Assert(reader.NamespaceURI != null);
            return reader.NamespaceURI.Length == 0 && reader.LocalName == localName;
        } 

        protected virtual bool HandleAttribute(XmlReader reader) 
        { 
            if(CanHandleAttribute(reader, XmlConstants.Name))
            { 
                HandleNameAttribute(reader);
                return true;
            }
 
            return false;
        } 
 
        private bool AddOtherContent(XmlReader reader)
        { 
            MetadataProperty property;
            if (reader.NodeType == XmlNodeType.Element)
            {
                // skip this element 
                // we don't support element annotations yet
                return true; 
 
                //// using this subtree aproach because when I call
                //// reader.ReadOuterXml() it positions me at the Node beyond 
                //// the end of the node I am starting on
                //// which doesn't work with the parsing logic
                //using (XmlReader subtree = reader.ReadSubtree())
                //{ 
                //    subtree.Read();
                //    property = new MetadataProperty(reader.NamespaceURI + ":" + reader.LocalName, 
                //                           TypeUsage.NewTypeUsage(EdmProviderManifest.Instance.GetPrimitiveType(PrimitiveTypeKind.String)), 
                //                           subtree.ReadOuterXml());
                //} 
            }
            else
            {
                if (reader.NamespaceURI == XmlNamespaceNamespace) 
                {
                    // we don't bring in namespace definitions 
                    return true; 
                }
 
                Debug.Assert(reader.NodeType == XmlNodeType.Attribute, "called an attribute function when not on an attribute");
                property = CreateMetadataPropertyFromOtherNamespaceXmlAttribute(reader.NamespaceURI, reader.LocalName, reader.Value);
            }
 
            OtherContent.Add(property);
            return false; 
        } 

        internal static MetadataProperty CreateMetadataPropertyFromOtherNamespaceXmlAttribute(string xmlNamespaceUri, string attributeName, string value) 
        {
            MetadataProperty property;
            property = new MetadataProperty( xmlNamespaceUri + ":" + attributeName,
                                       TypeUsage.Create(EdmProviderManifest.Instance.GetPrimitiveType(PrimitiveTypeKind.String)), 
                                       value);
            return property; 
        } 

        internal static bool TrySplitExtendedMetadataPropertyName(string name, out string xmlNamespaceUri, out string attributeName) 
        {
            int pos = name.LastIndexOf(':');
            if (pos < 0 || name.Length <= pos + 1)
            { 
                Debug.Fail("the name is not in the form we expect");
                xmlNamespaceUri = null; 
                attributeName = null; 
                return false;
            } 

            xmlNamespaceUri = name.Substring(0, pos);
            attributeName = name.Substring(pos +1, (name.Length - 1) - pos);
            return true; 
        }
 
        ///  
        /// Call handler for the current element
        ///  
        /// XmlReader positioned at the element
        /// true if element content should be skipped
        private bool ParseElement(XmlReader reader)
        { 
            string elementNamespace = reader.NamespaceURI;
            if (!Schema.IsParseableXmlNamespace(elementNamespace, true)) 
            { 
                return AddOtherContent(reader);
            } 
            if (HandleElement(reader))
            {
                return false;
            } 
            else
            { 
 
                // we need to report an error if the namespace for this element is a target namespace for the xml schemas we are parsing against.
                // otherwise we assume that this is either a valid 'any' element or that the xsd validator has generated an error 
                if (string.IsNullOrEmpty(elementNamespace) || Schema.IsParseableXmlNamespace(reader.NamespaceURI, false))
                {
                    AddError(ErrorCode.UnexpectedXmlElement, EdmSchemaErrorSeverity.Error, reader, System.Data.Entity.Strings.UnexpectedXmlElement(reader.Name));
                } 
                return true;
            } 
        } 

        protected bool CanHandleElement(XmlReader reader, string localName) 
        {
            return reader.NamespaceURI == Schema.SchemaXmlNamespace && reader.LocalName == localName;
        }
 
        protected virtual bool HandleElement(XmlReader reader)
        { 
            if (CanHandleElement(reader, XmlConstants.Documentation)) 
            {
                HandleDocumentationElement(reader); 
                return true;
            }
            return false;
        } 

        ///  
        /// Handle text data. 
        /// 
        /// XmlReader positioned at Text, CData, or SignificantWhitespace  
        private void ParseText(XmlReader reader)
        {
            if (HandleText(reader))
            { 
                return;
            } 
            else if (reader.Value != null && reader.Value.Trim().Length == 0) 
            {
                // just ignore this text.  Don't add an error, since the value is just whitespace. 
            }
            else
            {
                AddError( ErrorCode.TextNotAllowed, EdmSchemaErrorSeverity.Error, reader, System.Data.Entity.Strings.TextNotAllowed(reader.Value ) ); 
            }
        } 
        #endregion 

        [Conditional("DEBUG")] 
        internal static void AssertReaderConsidersSchemaInvalid(XmlReader reader)
        {
            Debug.Assert(reader.SchemaInfo == null ||
                         reader.SchemaInfo.Validity != System.Xml.Schema.XmlSchemaValidity.Valid, "The xsd should see this as not acceptable"); 
        }
 
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// 
// @owner       [....]
// @backupOwner [....] 
//--------------------------------------------------------------------- 

using System; 
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics; 
using System.Xml;
using System.Data; 
using System.Data.Metadata.Edm; 
using System.Reflection;
using System.Data.Entity; 



namespace System.Data.EntityModel.SchemaObjectModel 
{
    ///  
    /// Summary description for SchemaElement. 
    /// 
    [DebuggerDisplay("Name={Name}")] 
    internal abstract class SchemaElement
    {
        // see http://www.w3.org/TR/2006/REC-xml-names-20060816/
        internal const string XmlNamespaceNamespace = "http://www.w3.org/2000/xmlns/"; 

 
        #region Instance Fields 
        private SchemaElement _parentElement = null;
        private Schema _schema = null; 
        private int _lineNumber = 0;
        private int _linePosition = 0;
        private string _name = null;
        private DocumentationElement _documentation = null; 

        private List _otherContent; 
 
        #endregion
 
        #region Static Fields
        /// 
        protected const int MaxValueVersionComponent = short.MaxValue;
        #endregion 

        #region Public Properties 
        ///  
        ///
        ///  
        internal  int LineNumber
        {
            get
            { 
                return _lineNumber;
            } 
        } 

        ///  
        ///
        /// 
        internal  int LinePosition
        { 
            get
            { 
                return _linePosition; 
            }
        } 

        /// 
        ///
        ///  
        public virtual string Name
        { 
            get 
            {
                return _name; 
            }
            set
            {
                _name = value; 
            }
        } 
 
        /// 
        /// 
        /// 
        internal  DocumentationElement Documentation
        {
            get 
            {
                return _documentation; 
            } 
            set
            { 
                _documentation = value;
            }
        }
 
        /// 
        /// 
        ///  
        internal  SchemaElement ParentElement
        { 
            get
            {
                return _parentElement;
            } 
            private set
            { 
                _parentElement = value; 
            }
        } 

        /// 
        ///
        ///  
        internal Schema Schema
        { 
            get 
            {
                return _schema; 
            }
            set
            {
                _schema = value; 
            }
        } 
 
        /// 
        /// 
        /// 
        public  virtual string FQName
        {
            get 
            {
                return Name; 
            } 
        }
 
        /// 
        ///
        /// 
        public virtual string Identity 
        {
            get 
            { 
                return Name;
            } 
        }


        public List OtherContent 
        {
            get 
            { 
                if (_otherContent == null)
                { 
                    _otherContent = new List();
                }

                return _otherContent; 
            }
        } 
        #endregion 

        #region Internal Methods 
        /// 
        /// Validates this element and its children
        /// 
 
        internal virtual void Validate()
        { 
        } 

        ///  
        ///
        /// 
        internal void AddAlreadyDefinedError(XmlReader reader)
        { 
            AddError( ErrorCode.AlreadyDefined, EdmSchemaErrorSeverity.Error, reader, System.Data.Entity.Strings.AlreadyDefined(reader.Name ) );
        } 
 
        /// 
        /// 
        /// 
        /// 
        /// 
        ///  
        /// 
        ///  
        internal void AddError( ErrorCode errorCode, EdmSchemaErrorSeverity severity, int lineNumber, int linePosition, object message ) 
        {
            AddError(errorCode,severity,SchemaLocation,lineNumber,linePosition,message); 
        }

        /// 
        /// 
        /// 
        ///  
        ///  
        /// 
        ///  
        internal void AddError( ErrorCode errorCode, EdmSchemaErrorSeverity severity, XmlReader reader, object message )
        {
            int lineNumber;
            int linePosition; 
            GetPositionInfo(reader, out lineNumber, out linePosition);
            AddError(errorCode,severity,SchemaLocation,lineNumber,linePosition,message); 
        } 

        ///  
        ///
        /// 
        /// 
        ///  
        /// 
        internal void AddError( ErrorCode errorCode, EdmSchemaErrorSeverity severity, object message ) 
        { 
            AddError(errorCode,severity,SchemaLocation,LineNumber,LinePosition,message);
        } 

        /// 
        ///
        ///  
        /// 
        ///  
        ///  
        /// 
        internal void AddError( ErrorCode errorCode, EdmSchemaErrorSeverity severity, SchemaElement element, object message ) 
        {
            AddError(errorCode,severity,element.Schema.Location,element.LineNumber,element.LinePosition,message);
        }
 
        /// 
        /// 
        ///  
        /// 
        ///  
        internal void Parse(XmlReader reader)
        {
            GetPositionInfo(reader);
 
            bool hasEndElement = !reader.IsEmptyElement;
 
            Debug.Assert(reader.NodeType == XmlNodeType.Element); 
            for ( bool more = reader.MoveToFirstAttribute(); more; more = reader.MoveToNextAttribute() )
            { 
                ParseAttribute(reader);
            }
            HandleAttributesComplete();
 
            bool done = !hasEndElement;
            bool skipToNextElement = false; 
            while ( !done ) 
            {
                if ( skipToNextElement ) 
                {
                    skipToNextElement = false;
                    reader.Skip();
                    if ( reader.EOF ) 
                        break;
                } 
                else 
                {
                    if ( !reader.Read() ) 
                        break;
                }
                switch ( reader.NodeType )
                { 
                    case XmlNodeType.Element:
                        skipToNextElement = ParseElement(reader); 
                        break; 

                    case XmlNodeType.EndElement: 
                    {
                        done = true;
                        break;
                    } 

                    case XmlNodeType.CDATA: 
                    case XmlNodeType.Text: 
                    case XmlNodeType.SignificantWhitespace:
                        ParseText(reader); 
                        break;

                        // we ignore these childless elements
                    case XmlNodeType.Whitespace: 
                    case XmlNodeType.XmlDeclaration:
                    case XmlNodeType.Comment: 
                    case XmlNodeType.Notation: 
                    case XmlNodeType.ProcessingInstruction:
                    { 
                        break;
                    }

                        // we ignore these elements that can have children 
                    case XmlNodeType.DocumentType:
                    case XmlNodeType.EntityReference: 
                    { 
                        skipToNextElement = true;
                        break; 
                    }

                    default:
                    { 
                        AddError( ErrorCode.UnexpectedXmlNodeType, EdmSchemaErrorSeverity.Error, reader,
                            System.Data.Entity.Strings.UnexpectedXmlNodeType(reader.NodeType)); 
                        skipToNextElement = true; 
                        break;
                    } 
                }
            }
            HandleChildElementsComplete();
            if ( reader.EOF && reader.Depth > 0 ) 
            {
                AddError( ErrorCode.MalformedXml, EdmSchemaErrorSeverity.Error, 0, 0, 
                    System.Data.Entity.Strings.MalformedXml(LineNumber,LinePosition)); 
            }
        } 

        /// 
        /// Set the current line number and position for an XmlReader
        ///  
        /// the reader whose position is desired
        internal void GetPositionInfo(XmlReader reader) 
        { 
            GetPositionInfo(reader,out _lineNumber,out _linePosition);
        } 

        /// 
        /// Get the current line number and position for an XmlReader
        ///  
        /// the reader whose position is desired
        /// the line number 
        /// the line position 
        internal static void GetPositionInfo(XmlReader reader, out int lineNumber, out int linePosition)
        { 
            IXmlLineInfo xmlLineInfo = reader as IXmlLineInfo;
            if ( xmlLineInfo != null && xmlLineInfo.HasLineInfo() )
            {
                lineNumber = xmlLineInfo.LineNumber; 
                linePosition = xmlLineInfo.LinePosition;
            } 
            else 
            {
                lineNumber = 0; 
                linePosition = 0;
            }
        }
 
        /// 
        /// 
        ///  
        internal virtual void ResolveTopLevelNames()
        { 
        }
        internal virtual void ResolveSecondLevelNames()
        {
        } 
        #endregion
 
        #region Protected Methods 

        ///  
        ///
        /// 
        /// 
        internal SchemaElement(SchemaElement parentElement) 
        {
            if ( parentElement != null ) 
            { 
                ParentElement = parentElement;
                for ( SchemaElement element = parentElement; element != null; element = element.ParentElement ) 
                {
                    Schema schema = element as Schema;
                    if ( schema != null )
                    { 
                        Schema = schema;
                        break; 
                    } 
                }
 
                if (Schema == null)
                {
                    throw EntityUtil.InvalidOperation(System.Data.Entity.Strings.AllElementsMustBeInSchema);
                } 
            }
        } 
 
        internal SchemaElement(SchemaElement parentElement, string name)
            : this(parentElement) 
        {
            _name = name;
        }
 
        /// 
        /// 
        ///  
        protected virtual void HandleAttributesComplete()
        { 
        }

        /// 
        /// 
        /// 
        protected virtual void HandleChildElementsComplete() 
        { 
        }
 
        /// 
        ///
        /// 
        ///  
        /// 
        ///  
        protected string HandleUndottedNameAttribute(XmlReader reader, string field) 
        {
            string name = field; 
            if ( !string.IsNullOrEmpty(field) )
            {
                AddAlreadyDefinedError(reader);
                return name; 
            }
 
            bool success = Utils.GetUndottedName(Schema, reader, out name); 
            if ( !success )
                return name; 

            return name;
        }
 
        /// 
        /// 
        ///  
        /// 
        ///  
        /// 
        /// 
        protected ReturnValue HandleDottedNameAttribute(XmlReader reader, string field, Func errorFormat)
        { 
            ReturnValue returnValue = new ReturnValue();
            if ( !string.IsNullOrEmpty(field) ) 
            { 
                AddError( ErrorCode.AlreadyDefined, EdmSchemaErrorSeverity.Error, reader, errorFormat(reader.Name) );
                return returnValue; 
            }

            string value;
            if ( !Utils.GetDottedName(Schema,reader,out value) ) 
                return returnValue;
 
            returnValue.Value = value; 
            return returnValue;
        } 

        /// 
        /// Use to handle an attribute with an int data type
        ///  
        /// the reader positioned at the int attribute
        /// The int field to be given the value found 
        /// true if an int value was successfuly extracted from the attribute, false otherwise. 
        internal bool HandleIntAttribute(XmlReader reader, ref int field)
        { 
            int value;
            if ( !Utils.GetInt(Schema, reader, out value) )
                return false;
 
            field = value;
            return true; 
        } 

        ///  
        /// Use to handle an attribute with an int data type
        /// 
        /// the reader positioned at the int attribute
        /// The int field to be given the value found 
        /// true if an int value was successfuly extracted from the attribute, false otherwise.
        internal bool HandleByteAttribute(XmlReader reader, ref byte field) 
        { 
            byte value;
            if ( !Utils.GetByte(Schema, reader, out value) ) 
                return false;

            field = value;
            return true; 
        }
        ///  
        /// 
        /// 
        ///  
        /// 
        /// 
        internal bool HandleBoolAttribute(XmlReader reader,ref bool field)
        { 
            bool value;
            if ( !Utils.GetBool(Schema,reader,out value) ) 
                return false; 

            field = value; 
            return true;
        }

        ///  
        /// Use this to jump through an element that doesn't need any processing
        ///  
        /// xml reader currently positioned at an element 
        protected virtual void SkipThroughElement(XmlReader reader)
        { 
            Debug.Assert(reader != null);
            Parse(reader);
        }
 
        #endregion
 
        #region Protected Properties 
        /// 
        /// 
        /// 
        protected string SchemaLocation
        {
            get 
            {
                if ( Schema != null ) 
                    return Schema.Location; 
                return null;
            } 
        }

        protected virtual bool HandleText(XmlReader reader)
        { 
            return false;
        } 
 
        internal virtual SchemaElement Clone(SchemaElement parentElement)
        { 
            throw Error.NotImplemented();
        }
        #endregion
 
        #region Private Methods
        ///  
        /// 
        /// 
        ///  
        /// 
        private void HandleDocumentationElement(XmlReader reader)
        {
            if ( Documentation != null ) 
                AddAlreadyDefinedError(reader);
 
            Documentation = new DocumentationElement(this); 
            Documentation.Parse(reader);
        } 

        /// 
        ///
        ///  
        /// 
        protected virtual void HandleNameAttribute(XmlReader reader) 
        { 
            Name = HandleUndottedNameAttribute(reader, Name);
        } 

        /// 
        ///
        ///  
        /// 
        ///  
        ///  
        /// 
        ///  
        /// 
        private void AddError( ErrorCode errorCode, EdmSchemaErrorSeverity severity, string sourceLocation, int lineNumber, int linePosition, object message )
        {
            EdmSchemaError error = null; 
            string messageString = message as string;
            if ( messageString != null ) 
                error = new EdmSchemaError( messageString, (int)errorCode, severity, sourceLocation, lineNumber, linePosition ); 
            else
            { 
                Exception ex = message as Exception;
                if ( ex != null )
                    error = new EdmSchemaError( ex.Message, (int)errorCode, severity, sourceLocation, lineNumber, linePosition, ex );
                else 
                    error = new EdmSchemaError( message.ToString(), (int)errorCode, severity, sourceLocation, lineNumber, linePosition );
            } 
            Schema.AddError(error); 
        }
 
        /// 
        /// Call handler for the current attribute
        /// 
        /// XmlReader positioned at the attribute 
        private void ParseAttribute(XmlReader reader)
        { 
#if false 
            // the attribute value is schema invalid, just skip it; this avoids some duplicate errors at the expense of better error messages...
            if ( reader.SchemaInfo != null && reader.SchemaInfo.Validity == System.Xml.Schema.XmlSchemaValidity.Invalid ) 
                continue;
#endif
            string attributeNamespace = reader.NamespaceURI;
            if (!Schema.IsParseableXmlNamespace(attributeNamespace, true)) 
            {
                AddOtherContent(reader); 
            } 
            else if (!ProhibitAttribute(attributeNamespace, reader.LocalName)&&
                     HandleAttribute(reader)) 
            {
                return;
            }
            else if (reader.SchemaInfo == null || reader.SchemaInfo.Validity != System.Xml.Schema.XmlSchemaValidity.Invalid) 
            {
                // there's no handler for (namespace,name) and there wasn't a validation error. 
                // Report an error of our own if the node is in no namespace or if it is in one of our xml schemas tartget namespace. 
                if (string.IsNullOrEmpty(attributeNamespace) || Schema.IsParseableXmlNamespace(attributeNamespace, true))
                { 
                    AddError(ErrorCode.UnexpectedXmlAttribute, EdmSchemaErrorSeverity.Error, reader, System.Data.Entity.Strings.UnexpectedXmlAttribute(reader.Name));
                }
            }
        } 

        protected virtual bool ProhibitAttribute(string namespaceUri, string localName) 
        { 
            return false;
        } 


        /// 
        /// This overload assumes the default namespace 
        /// 
        ///  
        ///  
        /// 
        internal static bool CanHandleAttribute(XmlReader reader, string localName) 
        {
            Debug.Assert(reader.NamespaceURI != null);
            return reader.NamespaceURI.Length == 0 && reader.LocalName == localName;
        } 

        protected virtual bool HandleAttribute(XmlReader reader) 
        { 
            if(CanHandleAttribute(reader, XmlConstants.Name))
            { 
                HandleNameAttribute(reader);
                return true;
            }
 
            return false;
        } 
 
        private bool AddOtherContent(XmlReader reader)
        { 
            MetadataProperty property;
            if (reader.NodeType == XmlNodeType.Element)
            {
                // skip this element 
                // we don't support element annotations yet
                return true; 
 
                //// using this subtree aproach because when I call
                //// reader.ReadOuterXml() it positions me at the Node beyond 
                //// the end of the node I am starting on
                //// which doesn't work with the parsing logic
                //using (XmlReader subtree = reader.ReadSubtree())
                //{ 
                //    subtree.Read();
                //    property = new MetadataProperty(reader.NamespaceURI + ":" + reader.LocalName, 
                //                           TypeUsage.NewTypeUsage(EdmProviderManifest.Instance.GetPrimitiveType(PrimitiveTypeKind.String)), 
                //                           subtree.ReadOuterXml());
                //} 
            }
            else
            {
                if (reader.NamespaceURI == XmlNamespaceNamespace) 
                {
                    // we don't bring in namespace definitions 
                    return true; 
                }
 
                Debug.Assert(reader.NodeType == XmlNodeType.Attribute, "called an attribute function when not on an attribute");
                property = CreateMetadataPropertyFromOtherNamespaceXmlAttribute(reader.NamespaceURI, reader.LocalName, reader.Value);
            }
 
            OtherContent.Add(property);
            return false; 
        } 

        internal static MetadataProperty CreateMetadataPropertyFromOtherNamespaceXmlAttribute(string xmlNamespaceUri, string attributeName, string value) 
        {
            MetadataProperty property;
            property = new MetadataProperty( xmlNamespaceUri + ":" + attributeName,
                                       TypeUsage.Create(EdmProviderManifest.Instance.GetPrimitiveType(PrimitiveTypeKind.String)), 
                                       value);
            return property; 
        } 

        internal static bool TrySplitExtendedMetadataPropertyName(string name, out string xmlNamespaceUri, out string attributeName) 
        {
            int pos = name.LastIndexOf(':');
            if (pos < 0 || name.Length <= pos + 1)
            { 
                Debug.Fail("the name is not in the form we expect");
                xmlNamespaceUri = null; 
                attributeName = null; 
                return false;
            } 

            xmlNamespaceUri = name.Substring(0, pos);
            attributeName = name.Substring(pos +1, (name.Length - 1) - pos);
            return true; 
        }
 
        ///  
        /// Call handler for the current element
        ///  
        /// XmlReader positioned at the element
        /// true if element content should be skipped
        private bool ParseElement(XmlReader reader)
        { 
            string elementNamespace = reader.NamespaceURI;
            if (!Schema.IsParseableXmlNamespace(elementNamespace, true)) 
            { 
                return AddOtherContent(reader);
            } 
            if (HandleElement(reader))
            {
                return false;
            } 
            else
            { 
 
                // we need to report an error if the namespace for this element is a target namespace for the xml schemas we are parsing against.
                // otherwise we assume that this is either a valid 'any' element or that the xsd validator has generated an error 
                if (string.IsNullOrEmpty(elementNamespace) || Schema.IsParseableXmlNamespace(reader.NamespaceURI, false))
                {
                    AddError(ErrorCode.UnexpectedXmlElement, EdmSchemaErrorSeverity.Error, reader, System.Data.Entity.Strings.UnexpectedXmlElement(reader.Name));
                } 
                return true;
            } 
        } 

        protected bool CanHandleElement(XmlReader reader, string localName) 
        {
            return reader.NamespaceURI == Schema.SchemaXmlNamespace && reader.LocalName == localName;
        }
 
        protected virtual bool HandleElement(XmlReader reader)
        { 
            if (CanHandleElement(reader, XmlConstants.Documentation)) 
            {
                HandleDocumentationElement(reader); 
                return true;
            }
            return false;
        } 

        ///  
        /// Handle text data. 
        /// 
        /// XmlReader positioned at Text, CData, or SignificantWhitespace  
        private void ParseText(XmlReader reader)
        {
            if (HandleText(reader))
            { 
                return;
            } 
            else if (reader.Value != null && reader.Value.Trim().Length == 0) 
            {
                // just ignore this text.  Don't add an error, since the value is just whitespace. 
            }
            else
            {
                AddError( ErrorCode.TextNotAllowed, EdmSchemaErrorSeverity.Error, reader, System.Data.Entity.Strings.TextNotAllowed(reader.Value ) ); 
            }
        } 
        #endregion 

        [Conditional("DEBUG")] 
        internal static void AssertReaderConsidersSchemaInvalid(XmlReader reader)
        {
            Debug.Assert(reader.SchemaInfo == null ||
                         reader.SchemaInfo.Validity != System.Xml.Schema.XmlSchemaValidity.Valid, "The xsd should see this as not acceptable"); 
        }
 
    } 
}

// 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