internal ODataAtomInputContext(
            ODataFormat format,
            Stream messageStream,
            Encoding encoding,
            ODataMessageReaderSettings messageReaderSettings,
            bool readingResponse,
            bool synchronous,
            IEdmModel model,
            IODataUrlResolver urlResolver)
            : base(format, messageReaderSettings, readingResponse, synchronous, model, urlResolver)
        {
            Debug.Assert(messageStream != null, "stream != null");

            try
            {
                ExceptionUtils.CheckArgumentNotNull(format, "format");
                ExceptionUtils.CheckArgumentNotNull(messageReaderSettings, "messageReaderSettings");

                // Which encoding do we use when reading XML payloads
                this.baseXmlReader = ODataAtomReaderUtils.CreateXmlReader(messageStream, encoding, messageReaderSettings);

                // For WCF DS Server behavior we need to turn off xml:base processing for V1/V2 back compat.
                this.xmlReader = new BufferingXmlReader(
                    this.baseXmlReader,
                    /*parentXmlReader*/ null,
                    messageReaderSettings.BaseUri,
                    /*disableXmlBase*/ false,
                    messageReaderSettings.MessageQuotas.MaxNestingDepth);
            }
            catch (Exception e)
            {
                // Dispose the message stream if we failed to create the input context.
                if (ExceptionUtils.IsCatchableExceptionType(e) && messageStream != null)
                {
                    messageStream.Dispose();
                }

                throw;
            }
        }
        /// <summary>
        /// Reads the content of an error element.
        /// </summary>
        /// <param name="xmlReader">The Xml reader to read the error payload from.</param>
        /// <param name="maxInnerErrorDepth">The maximumum number of recursive internalexception elements to allow.</param>
        /// <returns>The <see cref="ODataError"/> representing the error.</returns>
        /// <remarks>
        /// This method is used to read top-level errors as well as in-stream errors (from inside the buffering Xml reader).
        /// Pre-Condition:  XmlNodeType.Element   - The m:error start element.
        /// Post-Condition: XmlNodeType.EndElement - The m:error end-element.
        ///                 XmlNodeType.Element    - The empty m:error start element.
        /// </remarks>
        internal static ODataError ReadErrorElement(BufferingXmlReader xmlReader, int maxInnerErrorDepth)
        {
            Debug.Assert(xmlReader != null, "this.XmlReader != null");
            Debug.Assert(xmlReader.NodeType == XmlNodeType.Element, "xmlReader.NodeType == XmlNodeType.Element");
            Debug.Assert(xmlReader.LocalName == AtomConstants.ODataErrorElementName, "Expected reader to be positioned on <m:error> element.");
            Debug.Assert(xmlReader.NamespaceEquals(xmlReader.ODataMetadataNamespace), "this.XmlReader.NamespaceEquals(atomizedMetadataNamespace)");

            ODataError error = new ODataError();
            DuplicateErrorElementPropertyBitMask elementsReadBitmask = DuplicateErrorElementPropertyBitMask.None;

            if (!xmlReader.IsEmptyElement)
            {
                // Move to the first child node of the element.
                xmlReader.Read();

                do
                {
                    switch (xmlReader.NodeType)
                    {
                        case XmlNodeType.EndElement:
                            // end of the <m:error> element
                            continue;

                        case XmlNodeType.Element:
                            if (xmlReader.NamespaceEquals(xmlReader.ODataMetadataNamespace))
                            {
                                switch (xmlReader.LocalName)
                                {
                                    // <m:code>
                                    case AtomConstants.ODataErrorCodeElementName:
                                        VerifyErrorElementNotFound(
                                            ref elementsReadBitmask,
                                            DuplicateErrorElementPropertyBitMask.Code,
                                            AtomConstants.ODataErrorCodeElementName);
                                        error.ErrorCode = xmlReader.ReadElementValue();
                                        continue;

                                    // <m:message >
                                    case AtomConstants.ODataErrorMessageElementName:
                                        VerifyErrorElementNotFound(
                                            ref elementsReadBitmask,
                                            DuplicateErrorElementPropertyBitMask.Message,
                                            AtomConstants.ODataErrorMessageElementName);
                                        error.Message = xmlReader.ReadElementValue();
                                        continue;

                                    // <m:innererror>
                                    case AtomConstants.ODataInnerErrorElementName:
                                        VerifyErrorElementNotFound(
                                            ref elementsReadBitmask,
                                            DuplicateErrorElementPropertyBitMask.InnerError,
                                            AtomConstants.ODataInnerErrorElementName);
                                        error.InnerError = ReadInnerErrorElement(xmlReader, 0 /* recursionDepth */, maxInnerErrorDepth);
                                        continue;

                                    default:
                                        break;
                                }
                            }

                            break;
                        default:
                            break;
                    }

                    xmlReader.Skip();
                }
                while (xmlReader.NodeType != XmlNodeType.EndElement);
            }

            return error;
        }
        /// <summary>
        /// Reads the content of an inner error element.
        /// </summary>
        /// <param name="xmlReader">The (buffering) Xml reader to read the error payload from.</param>
        /// <param name="recursionDepth">The number of times this function has been called recursively.</param>
        /// <param name="maxInnerErrorDepth">The maximumum number of recursive internalexception elements to allow.</param>
        /// <returns>The <see cref="ODataInnerError"/> representing the inner error.</returns>
        /// <remarks>
        /// Pre-Condition:  XmlNodeType.Element - the m:innererror or m:internalexception element
        /// Post-Condition: Any                 - the node after the m:innererror/m:internalexception end element or the node after the empty m:innererror/m:internalexception element node.
        /// </remarks>
        private static ODataInnerError ReadInnerErrorElement(BufferingXmlReader xmlReader, int recursionDepth, int maxInnerErrorDepth)
        {
            Debug.Assert(xmlReader != null, "this.XmlReader != null");
            Debug.Assert(xmlReader.NodeType == XmlNodeType.Element, "xmlReader.NodeType == XmlNodeType.Element");
            Debug.Assert(
                xmlReader.LocalName == AtomConstants.ODataInnerErrorElementName || 
                xmlReader.LocalName == AtomConstants.ODataInnerErrorInnerErrorElementName,
                "Expected reader to be positioned on 'm:innererror' or 'm:internalexception' element.");
            Debug.Assert(xmlReader.NamespaceEquals(xmlReader.ODataMetadataNamespace), "this.XmlReader.NamespaceEquals(this.ODataMetadataNamespace)");

            ValidationUtils.IncreaseAndValidateRecursionDepth(ref recursionDepth, maxInnerErrorDepth);

            ODataInnerError innerError = new ODataInnerError();
            DuplicateInnerErrorElementPropertyBitMask elementsReadBitmask = DuplicateInnerErrorElementPropertyBitMask.None;

            if (!xmlReader.IsEmptyElement)
            {
                // Move to the first child node of the element.
                xmlReader.Read();

                do
                {
                    switch (xmlReader.NodeType)
                    {
                        case XmlNodeType.EndElement:
                            // end of the <m:innererror> or <m:internalexception> element
                            continue;

                        case XmlNodeType.Element:
                            if (xmlReader.NamespaceEquals(xmlReader.ODataMetadataNamespace))
                            {
                                switch (xmlReader.LocalName)
                                {
                                    // <m:message>
                                    case AtomConstants.ODataInnerErrorMessageElementName:
                                        VerifyInnerErrorElementNotFound(
                                            ref elementsReadBitmask,
                                            DuplicateInnerErrorElementPropertyBitMask.Message,
                                            AtomConstants.ODataInnerErrorMessageElementName);
                                        innerError.Message = xmlReader.ReadElementValue();
                                        continue;

                                    // <m:type>
                                    case AtomConstants.ODataInnerErrorTypeElementName:
                                        VerifyInnerErrorElementNotFound(
                                            ref elementsReadBitmask,
                                            DuplicateInnerErrorElementPropertyBitMask.TypeName,
                                            AtomConstants.ODataInnerErrorTypeElementName);
                                        innerError.TypeName = xmlReader.ReadElementValue();
                                        continue;

                                    // <m:stacktrace>
                                    case AtomConstants.ODataInnerErrorStackTraceElementName:
                                        VerifyInnerErrorElementNotFound(
                                            ref elementsReadBitmask,
                                            DuplicateInnerErrorElementPropertyBitMask.StackTrace,
                                            AtomConstants.ODataInnerErrorStackTraceElementName);
                                        innerError.StackTrace = xmlReader.ReadElementValue();
                                        continue;

                                    // <m:internalexception>
                                    case AtomConstants.ODataInnerErrorInnerErrorElementName:
                                        VerifyInnerErrorElementNotFound(
                                            ref elementsReadBitmask,
                                            DuplicateInnerErrorElementPropertyBitMask.InternalException,
                                            AtomConstants.ODataInnerErrorInnerErrorElementName);
                                        innerError.InnerError = ReadInnerErrorElement(xmlReader, recursionDepth, maxInnerErrorDepth);
                                        continue;

                                    default:
                                        break;
                                }
                            }

                            break;
                        default:
                            break;
                    }

                    xmlReader.Skip();
                }
                while (xmlReader.NodeType != XmlNodeType.EndElement);
            }

            // Read over the end element, or empty start element.
            xmlReader.Read();

            return innerError;
        }
        /// <summary>
        /// Perform the actual cleanup work.
        /// </summary>
        /// <param name="disposing">If 'true' this method is called from user code; if 'false' it is called by the runtime.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                try
                {
                    if (this.baseXmlReader != null)
                    {
                        ((IDisposable)this.baseXmlReader).Dispose();
                    }
                }
                finally
                {
                    this.baseXmlReader = null;
                    this.xmlReader = null;
                }
            }

            base.Dispose(disposing);
        }