PlainXmlDeserializer.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / Orcas / NetFXw7 / ndp / fx / src / DataWeb / Server / System / Data / Services / Serializers / PlainXmlDeserializer.cs / 1 / PlainXmlDeserializer.cs

                            //---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//  
//      Provides a deserializer for plain XML content.
//  
// 
// @owner [....]
//--------------------------------------------------------------------- 

namespace System.Data.Services.Serializers
{
    using System; 
    using System.Diagnostics;
    using System.IO; 
    using System.Text; 
    using System.Xml;
    using System.Data.Services.Parsing; 
    using System.Data.Services.Providers;

    /// Provides a deserializer for plain XML content.
    internal class PlainXmlDeserializer : Deserializer 
    {
        /// reader to read xml from the request stream 
        private readonly XmlReader xmlReader; 

        /// Whether  is owned and should be disposed of. 
        private readonly bool xmlReaderOwned;

        /// Initializes a new  for the specified stream.
        /// Input stream reader from which POX content must be read. 
        /// Encoding to use for the stream (null to auto-discover).
        /// Data service for which the deserializer will act. 
        /// Indicates whether this is a PUT operation (rather than POST). 
        /// Tracker to use for modifications.
        internal PlainXmlDeserializer(Stream stream, Encoding encoding, IDataService dataService, bool update, UpdateTracker tracker) 
            : base(update, dataService, tracker)
        {
            Debug.Assert(stream != null, "stream != null");
            this.xmlReader = XmlUtil.CreateXmlReader(stream, encoding); 
            this.xmlReaderOwned = true;
        } 
 
        /// Initializes a new  based on the settings for another one.
        /// Reader for content. 
        /// Parent deserializer.
        internal PlainXmlDeserializer(XmlReader reader, Deserializer deserializer)
            : base(deserializer)
        { 
            Debug.Assert(reader != null, "reader != null");
            this.xmlReader = reader; 
 
            // this.xmlReaderOwned = false;
        } 

        /// Returns the content format for the deserializer.
        protected override ContentFormat ContentFormat
        { 
            get
            { 
                return ContentFormat.PlainXml; 
            }
        } 

        /// Applies properties from the reader to the specified resource.
        /// Deserializer which is driving the .
        /// XmlReader to read from. 
        /// Type of resource.
        /// Resource to set value on. 
        /// current object count for this operation. 
        /// 
        /// This method will end as soon as it find something that is not an 
        /// XML element to process.
        /// 
        internal static void ApplyContent(Deserializer deserializer, XmlReader reader, ResourceType resourceType, object resource, int currentObjectCount)
        { 
            Debug.Assert(deserializer != null, "deserializer != null");
            Debug.Assert(reader != null, "reader != null"); 
            using (PlainXmlDeserializer xml = new PlainXmlDeserializer(reader, deserializer)) 
            {
                // Initialize the new deserializer instance with the current object count 
                xml.UpdateObjectCount(currentObjectCount);

                // load all the properties
                xml.ApplyContent(xml.xmlReader, resourceType, resource); 

                // After all the properties have been loaded, initialize the current deserializer value with the object count 
                deserializer.UpdateObjectCount(xml.MaxObjectCount); 
            }
        } 

        /// 
        /// Converts the given value to the expected type as per XML serializer rules.
        /// Make sure these rules are in [....] with PlainXmlSerializer. 
        /// 
        /// value to the converted 
        /// name of the property whose value is getting converted 
        /// clr type to which the value needs to be converted to
        /// object which is in [....] with the properties type 
        internal static object ConvertValuesForXml(object value, string propertyName, Type typeToBeConverted)
        {
            Debug.Assert(WebUtil.IsPrimitiveType(typeToBeConverted), "WebUtil.IsPrimitiveType(typeToBeConverted)");
 
            string stringValue = value as string;
            if (stringValue != null) 
            { 
                try
                { 
                    value = WebConvert.StringToPrimitive(stringValue, typeToBeConverted);
                }
                catch (FormatException e)
                { 
                    throw DataServiceException.CreateBadRequestError(Strings.BadRequest_ErrorInConvertingPropertyValue(propertyName, typeToBeConverted), e);
                } 
            } 

            return value; 
        }

        /// 
        /// Assumes the payload to represent a single object and processes accordingly 
        /// 
        /// info about the object being created 
        /// the newly formed object that the payload represents 
        protected override object CreateSingleObject(SegmentInfo segmentInfo)
        { 
            Debug.Assert(
#if ASTORIA_OPEN_OBJECT
                segmentInfo.TargetKind == RequestTargetKind.OpenProperty ||
#endif 
                segmentInfo.TargetKind == RequestTargetKind.ComplexObject ||
                segmentInfo.TargetKind == RequestTargetKind.Primitive, 
                segmentInfo.TargetKind + " is one of open property; complex object; primitive -- otherwise the wrong serializer was chosen"); 

            if (!WebUtil.XmlReaderEnsureElement(this.xmlReader)) 
            {
                throw DataServiceException.CreateBadRequestError(Strings.PlainXml_PayloadLacksElement);
            }
 
            if (HasNullAttributeWithTrueValue(this.xmlReader))
            { 
                return null; 
            }
 
            ResourceType resourceType;
            string propertyName;
#if ASTORIA_OPEN_OBJECT
            if (segmentInfo.TargetKind == RequestTargetKind.OpenProperty) 
            {
                bool typeNameSpecified; 
                resourceType = this.ReadOpenPropertyTypeAttribute(this.xmlReader, out typeNameSpecified); 
                if (resourceType.ResourceTypeKind == ResourceTypeKind.EntityType)
                { 
                    throw DataServiceException.CreateBadRequestError(
                        Strings.PlainXml_EntityTypeNotSupported(resourceType.Type));
                }
 
                Debug.Assert(resourceType != null, "resourceType != null");
                propertyName = this.xmlReader.LocalName; 
            } 
            else
#endif 
            {
                Debug.Assert(segmentInfo.ProjectedProperty != null, "segmentInfo.ProjectedProperty != null");
                resourceType = segmentInfo.ProjectedProperty.ResourceType;
                propertyName = segmentInfo.ProjectedProperty.Name; 
                if (propertyName != this.xmlReader.LocalName)
                { 
                    throw DataServiceException.CreateBadRequestError( 
                        Strings.PlainXml_IncorrectElementName(propertyName, this.xmlReader.LocalName));
                } 
            }

            object result = this.ReadPropertyWithType(this.xmlReader, propertyName, resourceType);
            return result; 
        }
 
        /// Provides an opportunity to clean-up resources. 
        /// 
        /// Whether the call is being made from an explicit call to 
        /// IDisposable.Dispose() rather than through the finalizer.
        /// 
        protected override void Dispose(bool disposing)
        { 
            base.Dispose(disposing);
            if (disposing && this.xmlReaderOwned) 
            { 
                this.xmlReader.Close();
            } 
        }

        /// 
        /// Get the resource referred by the uri in the payload 
        /// 
        /// resource referred by the uri in the payload. 
        protected override string GetLinkUriFromPayload() 
        {
            if (!WebUtil.XmlReaderEnsureElement(this.xmlReader)) 
            {
                throw DataServiceException.CreateBadRequestError(Strings.PlainXml_PayloadLacksElement);
            }
 
            string uri = null;
            bool skipped; 
            do 
            {
                skipped = false; 
                switch (this.xmlReader.NodeType)
                {
                    case XmlNodeType.Element:
                        string localName = this.xmlReader.LocalName; 
                        string elementNamespace = this.xmlReader.NamespaceURI;
                        if (elementNamespace != XmlConstants.DataWebMetadataNamespace || 
                            localName != XmlConstants.UriElementName) 
                        {
                            this.xmlReader.Skip(); 
                            skipped = true;
                            continue;
                        }
 
                        if (uri != null)
                        { 
                            throw DataServiceException.CreateBadRequestError(Strings.BadRequest_MoreThanOneUriElementSpecified); 
                        }
 
                        uri = ReadElementString(this.xmlReader, localName);
                        if (String.IsNullOrEmpty(uri))
                        {
                            throw DataServiceException.CreateBadRequestError(Strings.BadRequest_MissingUriForLinkOperation); 
                        }
 
                        break; 
                    default:
                        break; 
                }
            }
            while (skipped || this.xmlReader.Read());
 
            Debug.Assert(
                this.xmlReader.NodeType != XmlNodeType.Element, 
                "reader.NodeType != XmlNodeType.Element -- otherwise we should have kept processing"); 

            if (String.IsNullOrEmpty(uri)) 
            {
                throw DataServiceException.CreateBadRequestError(Strings.BadRequest_MissingUriForLinkOperation);
            }
 
            return uri;
        } 
 
        /// 
        /// returns true if the null attribute is specified and the value is true 
        /// 
        /// xml reader from which attribute needs to be read
        /// true if the null attribute is specified and the attribute value is true
        private static bool HasNullAttributeWithTrueValue(XmlReader reader) 
        {
            Debug.Assert(reader != null, "reader != null"); 
            Debug.Assert(reader.NodeType == XmlNodeType.Element, "reader.NodeType == XmlNodeType.Element"); 

            string elementValue = reader.GetAttribute(XmlConstants.AtomNullAttributeName, XmlConstants.DataWebMetadataNamespace); 

            // If the null attribute is specified and the value is true, then set the property value to null,
            // otherwise set the value to empty string
            if ((null != elementValue) && XmlConvert.ToBoolean(elementValue)) 
            {
                string elementName = reader.LocalName; 
                if (!reader.IsEmptyElement) 
                {
                    reader.Read(); 
                    if (reader.NodeType != XmlNodeType.EndElement)
                    {
                        throw DataServiceException.CreateBadRequestError(
                            Strings.BadRequest_CannotSpecifyValueOrChildElementsForNullElement(elementName)); 
                    }
                } 
 
                return true;
            } 

            return false;
        }
 
        /// 
        /// Reads the value from the given element. This leaves the reader in the EndElement. 
        ///  
        /// xml reader from which the value needs to be read
        /// name of the element whose value is getting read 
        /// returns the xml string values as specified in the payload
        private static string ReadElementString(XmlReader reader, string elementName)
        {
            Debug.Assert(reader != null, "reader != null"); 
            Debug.Assert(XmlNodeType.Element == reader.NodeType, "not positioned on Element");
            string elementValue = null; 
 
            if (HasNullAttributeWithTrueValue(reader))
            { 
                return null;
            }
            else if (reader.IsEmptyElement)
            { 
                return String.Empty;
            } 
 
            StringBuilder builder = null;
            bool done = false; 
            while (!done && reader.Read())
            {
                switch (reader.NodeType)
                { 
                    case XmlNodeType.EndElement:
                        done = true; 
                        break; 
                    case XmlNodeType.CDATA:
                    case XmlNodeType.Text: 
                    case XmlNodeType.SignificantWhitespace:
                        if (elementValue == null)
                        {
                            elementValue = reader.Value; 
                        }
                        else if (builder == null) 
                        { 
                            string newValue = reader.Value;
                            builder = new StringBuilder(newValue.Length + elementValue.Length); 
                            builder.Append(elementValue);
                            builder.Append(newValue);
                        }
                        else 
                        {
                            builder.Append(reader.Value); 
                        } 

                        break; 
                    case XmlNodeType.Comment:
                    case XmlNodeType.Whitespace:
                        break;
 
                    #region XmlNodeType error
                    case XmlNodeType.None: 
                    case XmlNodeType.XmlDeclaration: 
                    case XmlNodeType.Attribute:
                    case XmlNodeType.EndEntity: 
                    case XmlNodeType.EntityReference:
                    case XmlNodeType.Entity:
                    case XmlNodeType.Document:
                    case XmlNodeType.DocumentType: 
                    case XmlNodeType.DocumentFragment:
                    case XmlNodeType.Notation: 
                    case XmlNodeType.ProcessingInstruction: 
                    default:
                        throw DataServiceException.CreateBadRequestError(Strings.BadRequest_InvalidValue(elementName)); 
                    #endregion
                }
            }
 
            if (builder != null)
            { 
                elementValue = builder.ToString(); 
            }
            else if (elementValue == null) 
            {
                elementValue = String.Empty;
            }
 
            return elementValue;
        } 
 
        /// Applies properties from the reader to the specified resource.
        /// XmlReader to read from. 
        /// Type of resource.
        /// Resource to set value on.
        /// 
        /// This method will end as soon as it find something that is not an 
        /// XML element to process.
        ///  
        private void ApplyContent(XmlReader reader, ResourceType resourceType, object resource) 
        {
            Debug.Assert(resourceType != null, "resourceType != null"); 
            Debug.Assert(resource != null, "resource != null");

            if (!WebUtil.XmlReaderEnsureElement(reader))
            { 
                return;
            } 
 
            this.RecurseEnter();
            bool skipped; 
            do
            {
                skipped = false;
                switch (reader.NodeType) 
                {
                    case XmlNodeType.Element: 
                        string localName = reader.LocalName; 
                        string elementNamespace = reader.NamespaceURI;
                        if (elementNamespace != XmlConstants.DataWebNamespace) 
                        {
                            reader.Skip();
                            skipped = true;
                            continue; 
                        }
 
                        this.ApplyProperty(reader, localName, resourceType, resource); 
                        break;
                    default: 
                        break;
                }
            }
            while (skipped || reader.Read()); 

            Debug.Assert( 
                reader.NodeType != XmlNodeType.Element, 
                "reader.NodeType != XmlNodeType.Element -- otherwise we should have kept processing");
            this.RecurseLeave(); 
        }

        /// Applies a property from the reader to the specified resource.
        /// XmlReader to read from. 
        /// Name of property to set on the specified resource.
        /// Type of resource. 
        /// Resource to set value on. 
        private void ApplyProperty(XmlReader reader, string propertyName, ResourceType resourceType, object resource)
        { 
            Debug.Assert(reader != null, "reader != null");
            Debug.Assert(propertyName != null, "propertyName != null");
            Debug.Assert(resourceType != null, "resourceType != null");
            Debug.Assert(resource != null, "resource != null"); 

            ResourceProperty property = resourceType.TryResolvePropertyName(propertyName); 
            ResourceType propertyType; 
            bool ignoreValue = false;
            if (property == null) 
            {
#if ASTORIA_OPEN_OBJECT
                if (resourceType.OpenTypeKind != OpenTypeKind.CompletelyOpen)
#endif 
                {
                    throw DataServiceException.CreateBadRequestError(Strings.BadRequest_InvalidPropertyNameSpecified(propertyName, resourceType.FullName)); 
                } 

#if ASTORIA_OPEN_OBJECT 
                bool typeNameSpecified;
                propertyType = this.ReadOpenPropertyTypeAttribute(reader, out typeNameSpecified);
#endif
            } 
            else
            { 
                propertyType = property.ResourceType; 
                if (this.Update && property.IsOfKind(ResourcePropertyKind.Key))
                { 
                    ignoreValue = true;
                }
            }
 
            object propertyValue = this.ReadPropertyWithType(reader, propertyName, propertyType);
            if (!ignoreValue) 
            { 
                this.Service.Provider.SetValue(resource, propertyName, propertyValue);
            } 
        }

#if ASTORIA_OPEN_OBJECT
 
        /// Gets the type attribute and resolves the type.
        /// reader from which type attribute needs to be read 
        /// true if the reader contains a type attribute otherwise false 
        /// resolved type
        private ResourceType ReadOpenPropertyTypeAttribute(XmlReader reader, out bool typeNameSpecified) 
        {
            Debug.Assert(reader != null, "reader != null");
            string typeName = reader.GetAttribute(XmlConstants.AtomTypeAttributeName, XmlConstants.DataWebMetadataNamespace);
            ResourceType resourceType = null; 

            // If the type is not specified in the payload, we assume the type to be the expected type 
            if (String.IsNullOrEmpty(typeName)) 
            {
                typeNameSpecified = false; 
                resourceType = this.Service.Provider.GetResourceType(typeof(string));
            }
            else
            { 
                typeNameSpecified = true;
 
                // try and resolve the name specified in the payload 
                resourceType = this.Service.Provider.TryResolveTypeName(typeName);
                if (resourceType == null) 
                {
                    throw DataServiceException.CreateBadRequestError(Strings.BadRequest_InvalidTypeName(typeName));
                }
            } 

            return resourceType; 
        } 

#endif 

        /// Reads a typed property from the specified XmlReader.
        /// XmlReader to read from.
        /// Name of property to read. 
        /// Type of property to read.
        /// The instance read, possibly null. 
        private object ReadPropertyWithType(XmlReader reader, string propertyName, ResourceType propertyType) 
        {
            Debug.Assert(reader != null, "reader != null"); 
            Debug.Assert(propertyName != null, "propertyName != null");
            Debug.Assert(propertyType != null, "propertyType != null");

            object propertyValue; 
            switch (propertyType.ResourceTypeKind)
            { 
                case ResourceTypeKind.ComplexType: 
                    this.CheckAndIncrementObjectCount();
                    if (HasNullAttributeWithTrueValue(reader)) 
                    {
                        propertyValue = null;
                    }
                    else 
                    {
                        propertyValue = this.Service.Provider.CreateResource(null, propertyType.FullName); 
                        if (!reader.IsEmptyElement) 
                        {
                            // Step inside the complex type, apply its properties, and pop back out. 
                            using (XmlReader propertyReader = reader.ReadSubtree())
                            {
                                if (!WebUtil.XmlReaderEnsureElement(propertyReader))
                                { 
                                    throw DataServiceException.CreateBadRequestError(
                                        Strings.PlainXml_PropertyLacksElement(propertyName)); 
                                } 

                                propertyReader.ReadStartElement(); 
                                ApplyContent(propertyReader, propertyType, propertyValue);
                            }

                            Debug.Assert( 
                                reader.NodeType == XmlNodeType.EndElement,
                                "reader.NodeType == XmlNodeType.EndElement -- otherwise ReadSubtree left outer read in incorrect position."); 
                        } 
                    }
 
                    break;
                case ResourceTypeKind.EntityType:
                    throw DataServiceException.CreateBadRequestError(
                        Strings.PlainXml_NavigationPropertyNotSupported(propertyName)); 
                default:
                    Debug.Assert( 
                        propertyType.ResourceTypeKind == ResourceTypeKind.Primitive, 
                        "property.TypeKind == ResourceTypeKind.Primitive -- metadata shouldn't return " + propertyType.ResourceTypeKind);
                    string stringValue = ReadElementString(reader, propertyName); 
                    propertyValue = PlainXmlDeserializer.ConvertValuesForXml(stringValue, propertyName, propertyType.Type);
                    break;
            }
 
            return propertyValue;
        } 
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//---------------------------------------------------------------------- 
// 
//      Copyright (c) Microsoft Corporation.  All rights reserved.
// 
//  
//      Provides a deserializer for plain XML content.
//  
// 
// @owner [....]
//--------------------------------------------------------------------- 

namespace System.Data.Services.Serializers
{
    using System; 
    using System.Diagnostics;
    using System.IO; 
    using System.Text; 
    using System.Xml;
    using System.Data.Services.Parsing; 
    using System.Data.Services.Providers;

    /// Provides a deserializer for plain XML content.
    internal class PlainXmlDeserializer : Deserializer 
    {
        /// reader to read xml from the request stream 
        private readonly XmlReader xmlReader; 

        /// Whether  is owned and should be disposed of. 
        private readonly bool xmlReaderOwned;

        /// Initializes a new  for the specified stream.
        /// Input stream reader from which POX content must be read. 
        /// Encoding to use for the stream (null to auto-discover).
        /// Data service for which the deserializer will act. 
        /// Indicates whether this is a PUT operation (rather than POST). 
        /// Tracker to use for modifications.
        internal PlainXmlDeserializer(Stream stream, Encoding encoding, IDataService dataService, bool update, UpdateTracker tracker) 
            : base(update, dataService, tracker)
        {
            Debug.Assert(stream != null, "stream != null");
            this.xmlReader = XmlUtil.CreateXmlReader(stream, encoding); 
            this.xmlReaderOwned = true;
        } 
 
        /// Initializes a new  based on the settings for another one.
        /// Reader for content. 
        /// Parent deserializer.
        internal PlainXmlDeserializer(XmlReader reader, Deserializer deserializer)
            : base(deserializer)
        { 
            Debug.Assert(reader != null, "reader != null");
            this.xmlReader = reader; 
 
            // this.xmlReaderOwned = false;
        } 

        /// Returns the content format for the deserializer.
        protected override ContentFormat ContentFormat
        { 
            get
            { 
                return ContentFormat.PlainXml; 
            }
        } 

        /// Applies properties from the reader to the specified resource.
        /// Deserializer which is driving the .
        /// XmlReader to read from. 
        /// Type of resource.
        /// Resource to set value on. 
        /// current object count for this operation. 
        /// 
        /// This method will end as soon as it find something that is not an 
        /// XML element to process.
        /// 
        internal static void ApplyContent(Deserializer deserializer, XmlReader reader, ResourceType resourceType, object resource, int currentObjectCount)
        { 
            Debug.Assert(deserializer != null, "deserializer != null");
            Debug.Assert(reader != null, "reader != null"); 
            using (PlainXmlDeserializer xml = new PlainXmlDeserializer(reader, deserializer)) 
            {
                // Initialize the new deserializer instance with the current object count 
                xml.UpdateObjectCount(currentObjectCount);

                // load all the properties
                xml.ApplyContent(xml.xmlReader, resourceType, resource); 

                // After all the properties have been loaded, initialize the current deserializer value with the object count 
                deserializer.UpdateObjectCount(xml.MaxObjectCount); 
            }
        } 

        /// 
        /// Converts the given value to the expected type as per XML serializer rules.
        /// Make sure these rules are in [....] with PlainXmlSerializer. 
        /// 
        /// value to the converted 
        /// name of the property whose value is getting converted 
        /// clr type to which the value needs to be converted to
        /// object which is in [....] with the properties type 
        internal static object ConvertValuesForXml(object value, string propertyName, Type typeToBeConverted)
        {
            Debug.Assert(WebUtil.IsPrimitiveType(typeToBeConverted), "WebUtil.IsPrimitiveType(typeToBeConverted)");
 
            string stringValue = value as string;
            if (stringValue != null) 
            { 
                try
                { 
                    value = WebConvert.StringToPrimitive(stringValue, typeToBeConverted);
                }
                catch (FormatException e)
                { 
                    throw DataServiceException.CreateBadRequestError(Strings.BadRequest_ErrorInConvertingPropertyValue(propertyName, typeToBeConverted), e);
                } 
            } 

            return value; 
        }

        /// 
        /// Assumes the payload to represent a single object and processes accordingly 
        /// 
        /// info about the object being created 
        /// the newly formed object that the payload represents 
        protected override object CreateSingleObject(SegmentInfo segmentInfo)
        { 
            Debug.Assert(
#if ASTORIA_OPEN_OBJECT
                segmentInfo.TargetKind == RequestTargetKind.OpenProperty ||
#endif 
                segmentInfo.TargetKind == RequestTargetKind.ComplexObject ||
                segmentInfo.TargetKind == RequestTargetKind.Primitive, 
                segmentInfo.TargetKind + " is one of open property; complex object; primitive -- otherwise the wrong serializer was chosen"); 

            if (!WebUtil.XmlReaderEnsureElement(this.xmlReader)) 
            {
                throw DataServiceException.CreateBadRequestError(Strings.PlainXml_PayloadLacksElement);
            }
 
            if (HasNullAttributeWithTrueValue(this.xmlReader))
            { 
                return null; 
            }
 
            ResourceType resourceType;
            string propertyName;
#if ASTORIA_OPEN_OBJECT
            if (segmentInfo.TargetKind == RequestTargetKind.OpenProperty) 
            {
                bool typeNameSpecified; 
                resourceType = this.ReadOpenPropertyTypeAttribute(this.xmlReader, out typeNameSpecified); 
                if (resourceType.ResourceTypeKind == ResourceTypeKind.EntityType)
                { 
                    throw DataServiceException.CreateBadRequestError(
                        Strings.PlainXml_EntityTypeNotSupported(resourceType.Type));
                }
 
                Debug.Assert(resourceType != null, "resourceType != null");
                propertyName = this.xmlReader.LocalName; 
            } 
            else
#endif 
            {
                Debug.Assert(segmentInfo.ProjectedProperty != null, "segmentInfo.ProjectedProperty != null");
                resourceType = segmentInfo.ProjectedProperty.ResourceType;
                propertyName = segmentInfo.ProjectedProperty.Name; 
                if (propertyName != this.xmlReader.LocalName)
                { 
                    throw DataServiceException.CreateBadRequestError( 
                        Strings.PlainXml_IncorrectElementName(propertyName, this.xmlReader.LocalName));
                } 
            }

            object result = this.ReadPropertyWithType(this.xmlReader, propertyName, resourceType);
            return result; 
        }
 
        /// Provides an opportunity to clean-up resources. 
        /// 
        /// Whether the call is being made from an explicit call to 
        /// IDisposable.Dispose() rather than through the finalizer.
        /// 
        protected override void Dispose(bool disposing)
        { 
            base.Dispose(disposing);
            if (disposing && this.xmlReaderOwned) 
            { 
                this.xmlReader.Close();
            } 
        }

        /// 
        /// Get the resource referred by the uri in the payload 
        /// 
        /// resource referred by the uri in the payload. 
        protected override string GetLinkUriFromPayload() 
        {
            if (!WebUtil.XmlReaderEnsureElement(this.xmlReader)) 
            {
                throw DataServiceException.CreateBadRequestError(Strings.PlainXml_PayloadLacksElement);
            }
 
            string uri = null;
            bool skipped; 
            do 
            {
                skipped = false; 
                switch (this.xmlReader.NodeType)
                {
                    case XmlNodeType.Element:
                        string localName = this.xmlReader.LocalName; 
                        string elementNamespace = this.xmlReader.NamespaceURI;
                        if (elementNamespace != XmlConstants.DataWebMetadataNamespace || 
                            localName != XmlConstants.UriElementName) 
                        {
                            this.xmlReader.Skip(); 
                            skipped = true;
                            continue;
                        }
 
                        if (uri != null)
                        { 
                            throw DataServiceException.CreateBadRequestError(Strings.BadRequest_MoreThanOneUriElementSpecified); 
                        }
 
                        uri = ReadElementString(this.xmlReader, localName);
                        if (String.IsNullOrEmpty(uri))
                        {
                            throw DataServiceException.CreateBadRequestError(Strings.BadRequest_MissingUriForLinkOperation); 
                        }
 
                        break; 
                    default:
                        break; 
                }
            }
            while (skipped || this.xmlReader.Read());
 
            Debug.Assert(
                this.xmlReader.NodeType != XmlNodeType.Element, 
                "reader.NodeType != XmlNodeType.Element -- otherwise we should have kept processing"); 

            if (String.IsNullOrEmpty(uri)) 
            {
                throw DataServiceException.CreateBadRequestError(Strings.BadRequest_MissingUriForLinkOperation);
            }
 
            return uri;
        } 
 
        /// 
        /// returns true if the null attribute is specified and the value is true 
        /// 
        /// xml reader from which attribute needs to be read
        /// true if the null attribute is specified and the attribute value is true
        private static bool HasNullAttributeWithTrueValue(XmlReader reader) 
        {
            Debug.Assert(reader != null, "reader != null"); 
            Debug.Assert(reader.NodeType == XmlNodeType.Element, "reader.NodeType == XmlNodeType.Element"); 

            string elementValue = reader.GetAttribute(XmlConstants.AtomNullAttributeName, XmlConstants.DataWebMetadataNamespace); 

            // If the null attribute is specified and the value is true, then set the property value to null,
            // otherwise set the value to empty string
            if ((null != elementValue) && XmlConvert.ToBoolean(elementValue)) 
            {
                string elementName = reader.LocalName; 
                if (!reader.IsEmptyElement) 
                {
                    reader.Read(); 
                    if (reader.NodeType != XmlNodeType.EndElement)
                    {
                        throw DataServiceException.CreateBadRequestError(
                            Strings.BadRequest_CannotSpecifyValueOrChildElementsForNullElement(elementName)); 
                    }
                } 
 
                return true;
            } 

            return false;
        }
 
        /// 
        /// Reads the value from the given element. This leaves the reader in the EndElement. 
        ///  
        /// xml reader from which the value needs to be read
        /// name of the element whose value is getting read 
        /// returns the xml string values as specified in the payload
        private static string ReadElementString(XmlReader reader, string elementName)
        {
            Debug.Assert(reader != null, "reader != null"); 
            Debug.Assert(XmlNodeType.Element == reader.NodeType, "not positioned on Element");
            string elementValue = null; 
 
            if (HasNullAttributeWithTrueValue(reader))
            { 
                return null;
            }
            else if (reader.IsEmptyElement)
            { 
                return String.Empty;
            } 
 
            StringBuilder builder = null;
            bool done = false; 
            while (!done && reader.Read())
            {
                switch (reader.NodeType)
                { 
                    case XmlNodeType.EndElement:
                        done = true; 
                        break; 
                    case XmlNodeType.CDATA:
                    case XmlNodeType.Text: 
                    case XmlNodeType.SignificantWhitespace:
                        if (elementValue == null)
                        {
                            elementValue = reader.Value; 
                        }
                        else if (builder == null) 
                        { 
                            string newValue = reader.Value;
                            builder = new StringBuilder(newValue.Length + elementValue.Length); 
                            builder.Append(elementValue);
                            builder.Append(newValue);
                        }
                        else 
                        {
                            builder.Append(reader.Value); 
                        } 

                        break; 
                    case XmlNodeType.Comment:
                    case XmlNodeType.Whitespace:
                        break;
 
                    #region XmlNodeType error
                    case XmlNodeType.None: 
                    case XmlNodeType.XmlDeclaration: 
                    case XmlNodeType.Attribute:
                    case XmlNodeType.EndEntity: 
                    case XmlNodeType.EntityReference:
                    case XmlNodeType.Entity:
                    case XmlNodeType.Document:
                    case XmlNodeType.DocumentType: 
                    case XmlNodeType.DocumentFragment:
                    case XmlNodeType.Notation: 
                    case XmlNodeType.ProcessingInstruction: 
                    default:
                        throw DataServiceException.CreateBadRequestError(Strings.BadRequest_InvalidValue(elementName)); 
                    #endregion
                }
            }
 
            if (builder != null)
            { 
                elementValue = builder.ToString(); 
            }
            else if (elementValue == null) 
            {
                elementValue = String.Empty;
            }
 
            return elementValue;
        } 
 
        /// Applies properties from the reader to the specified resource.
        /// XmlReader to read from. 
        /// Type of resource.
        /// Resource to set value on.
        /// 
        /// This method will end as soon as it find something that is not an 
        /// XML element to process.
        ///  
        private void ApplyContent(XmlReader reader, ResourceType resourceType, object resource) 
        {
            Debug.Assert(resourceType != null, "resourceType != null"); 
            Debug.Assert(resource != null, "resource != null");

            if (!WebUtil.XmlReaderEnsureElement(reader))
            { 
                return;
            } 
 
            this.RecurseEnter();
            bool skipped; 
            do
            {
                skipped = false;
                switch (reader.NodeType) 
                {
                    case XmlNodeType.Element: 
                        string localName = reader.LocalName; 
                        string elementNamespace = reader.NamespaceURI;
                        if (elementNamespace != XmlConstants.DataWebNamespace) 
                        {
                            reader.Skip();
                            skipped = true;
                            continue; 
                        }
 
                        this.ApplyProperty(reader, localName, resourceType, resource); 
                        break;
                    default: 
                        break;
                }
            }
            while (skipped || reader.Read()); 

            Debug.Assert( 
                reader.NodeType != XmlNodeType.Element, 
                "reader.NodeType != XmlNodeType.Element -- otherwise we should have kept processing");
            this.RecurseLeave(); 
        }

        /// Applies a property from the reader to the specified resource.
        /// XmlReader to read from. 
        /// Name of property to set on the specified resource.
        /// Type of resource. 
        /// Resource to set value on. 
        private void ApplyProperty(XmlReader reader, string propertyName, ResourceType resourceType, object resource)
        { 
            Debug.Assert(reader != null, "reader != null");
            Debug.Assert(propertyName != null, "propertyName != null");
            Debug.Assert(resourceType != null, "resourceType != null");
            Debug.Assert(resource != null, "resource != null"); 

            ResourceProperty property = resourceType.TryResolvePropertyName(propertyName); 
            ResourceType propertyType; 
            bool ignoreValue = false;
            if (property == null) 
            {
#if ASTORIA_OPEN_OBJECT
                if (resourceType.OpenTypeKind != OpenTypeKind.CompletelyOpen)
#endif 
                {
                    throw DataServiceException.CreateBadRequestError(Strings.BadRequest_InvalidPropertyNameSpecified(propertyName, resourceType.FullName)); 
                } 

#if ASTORIA_OPEN_OBJECT 
                bool typeNameSpecified;
                propertyType = this.ReadOpenPropertyTypeAttribute(reader, out typeNameSpecified);
#endif
            } 
            else
            { 
                propertyType = property.ResourceType; 
                if (this.Update && property.IsOfKind(ResourcePropertyKind.Key))
                { 
                    ignoreValue = true;
                }
            }
 
            object propertyValue = this.ReadPropertyWithType(reader, propertyName, propertyType);
            if (!ignoreValue) 
            { 
                this.Service.Provider.SetValue(resource, propertyName, propertyValue);
            } 
        }

#if ASTORIA_OPEN_OBJECT
 
        /// Gets the type attribute and resolves the type.
        /// reader from which type attribute needs to be read 
        /// true if the reader contains a type attribute otherwise false 
        /// resolved type
        private ResourceType ReadOpenPropertyTypeAttribute(XmlReader reader, out bool typeNameSpecified) 
        {
            Debug.Assert(reader != null, "reader != null");
            string typeName = reader.GetAttribute(XmlConstants.AtomTypeAttributeName, XmlConstants.DataWebMetadataNamespace);
            ResourceType resourceType = null; 

            // If the type is not specified in the payload, we assume the type to be the expected type 
            if (String.IsNullOrEmpty(typeName)) 
            {
                typeNameSpecified = false; 
                resourceType = this.Service.Provider.GetResourceType(typeof(string));
            }
            else
            { 
                typeNameSpecified = true;
 
                // try and resolve the name specified in the payload 
                resourceType = this.Service.Provider.TryResolveTypeName(typeName);
                if (resourceType == null) 
                {
                    throw DataServiceException.CreateBadRequestError(Strings.BadRequest_InvalidTypeName(typeName));
                }
            } 

            return resourceType; 
        } 

#endif 

        /// Reads a typed property from the specified XmlReader.
        /// XmlReader to read from.
        /// Name of property to read. 
        /// Type of property to read.
        /// The instance read, possibly null. 
        private object ReadPropertyWithType(XmlReader reader, string propertyName, ResourceType propertyType) 
        {
            Debug.Assert(reader != null, "reader != null"); 
            Debug.Assert(propertyName != null, "propertyName != null");
            Debug.Assert(propertyType != null, "propertyType != null");

            object propertyValue; 
            switch (propertyType.ResourceTypeKind)
            { 
                case ResourceTypeKind.ComplexType: 
                    this.CheckAndIncrementObjectCount();
                    if (HasNullAttributeWithTrueValue(reader)) 
                    {
                        propertyValue = null;
                    }
                    else 
                    {
                        propertyValue = this.Service.Provider.CreateResource(null, propertyType.FullName); 
                        if (!reader.IsEmptyElement) 
                        {
                            // Step inside the complex type, apply its properties, and pop back out. 
                            using (XmlReader propertyReader = reader.ReadSubtree())
                            {
                                if (!WebUtil.XmlReaderEnsureElement(propertyReader))
                                { 
                                    throw DataServiceException.CreateBadRequestError(
                                        Strings.PlainXml_PropertyLacksElement(propertyName)); 
                                } 

                                propertyReader.ReadStartElement(); 
                                ApplyContent(propertyReader, propertyType, propertyValue);
                            }

                            Debug.Assert( 
                                reader.NodeType == XmlNodeType.EndElement,
                                "reader.NodeType == XmlNodeType.EndElement -- otherwise ReadSubtree left outer read in incorrect position."); 
                        } 
                    }
 
                    break;
                case ResourceTypeKind.EntityType:
                    throw DataServiceException.CreateBadRequestError(
                        Strings.PlainXml_NavigationPropertyNotSupported(propertyName)); 
                default:
                    Debug.Assert( 
                        propertyType.ResourceTypeKind == ResourceTypeKind.Primitive, 
                        "property.TypeKind == ResourceTypeKind.Primitive -- metadata shouldn't return " + propertyType.ResourceTypeKind);
                    string stringValue = ReadElementString(reader, propertyName); 
                    propertyValue = PlainXmlDeserializer.ConvertValuesForXml(stringValue, propertyName, propertyType.Type);
                    break;
            }
 
            return propertyValue;
        } 
    } 
}

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