Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / DataWeb / Server / System / Data / Services / Serializers / PlainXmlDeserializer.cs / 1305376 / 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.Data.Services.Common; using System.Data.Services.Parsing; using System.Data.Services.Providers; using System.Diagnostics; using System.IO; using System.Text; using System.Xml; ///Provides a deserializer for plain XML content. internal class PlainXmlDeserializer : Deserializer { ///reader to read xml from the request stream private readonly XmlReader xmlReader; ///Whether private readonly bool xmlReaderOwned; ///is owned and should be disposed of. Properties already applied based on content private readonly EpmContentDeSerializer.EpmAppliedPropertyInfo propertiesApplied; ///Prefix of the path to use in private String currentPathPrefix; ///Initializes a new /// 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; } ///for the specified stream. Initializes a new /// Reader for content. /// Parent deserializer. /// Properties already applied based on content internal PlainXmlDeserializer(XmlReader reader, Deserializer deserializer, EpmContentDeSerializer.EpmAppliedPropertyInfo propertiesApplied) : base(deserializer) { Debug.Assert(reader != null, "reader != null"); this.xmlReader = reader; Debug.Assert(propertiesApplied != null, "Requires valid collection for applied properties"); this.propertiesApplied = propertiesApplied; this.currentPathPrefix = String.Empty; // this.xmlReaderOwned = false; } ///based on the settings for another one. 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. /// Properties already applied based on content /// 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, EpmContentDeSerializer.EpmAppliedPropertyInfo propertiesApplied, int currentObjectCount) { Debug.Assert(deserializer != null, "deserializer != null"); Debug.Assert(reader != null, "reader != null"); using (PlainXmlDeserializer xml = new PlainXmlDeserializer(reader, deserializer, propertiesApplied)) { // 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)"); Debug.Assert(value == null || value is string, "This method should be used only for converting string to a primitve value."); 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( segmentInfo.TargetKind == RequestTargetKind.OpenProperty || 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; } string propertyName; if (segmentInfo.TargetKind == RequestTargetKind.OpenProperty) { propertyName = this.xmlReader.LocalName; } else { Debug.Assert(segmentInfo.ProjectedProperty != null, "segmentInfo.ProjectedProperty != null"); Debug.Assert( segmentInfo.ProjectedProperty.ResourceType.ResourceTypeKind != ResourceTypeKind.EntityType, "entity types not expected in the PlainXmlDeserializer"); 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, segmentInfo.ProjectedProperty); 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 && elementNamespace != XmlConstants.DataWebNamespace) || 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); bool ignoreValue = false; if (property == null) { if (resourceType.IsOpenType == false) { throw DataServiceException.CreateBadRequestError(Strings.BadRequest_InvalidPropertyNameSpecified(propertyName, resourceType.FullName)); } } else { if (this.Update && property.IsOfKind(ResourcePropertyKind.Key)) { ignoreValue = true; } } object propertyValue = this.ReadPropertyWithType(reader, propertyName, property); if (!ignoreValue) { if (property == null) { Deserializer.SetOpenPropertyValue(resource, propertyName, propertyValue, this.Service); } else { Deserializer.SetPropertyValue(property, resource, propertyValue, this.ContentFormat, this.Service); } } } ///Gets the type attribute and resolves the type. /// reader from which type attribute needs to be read ///resolved type private ResourceType ReadOpenPropertyTypeAttribute(XmlReader reader) { 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)) { resourceType = ResourceType.PrimitiveStringResourceType; } else { // try and resolve the name specified in the payload resourceType = WebUtil.TryResolveResourceType(this.Service.Provider, typeName); if (resourceType == null) { throw DataServiceException.CreateBadRequestError(Strings.BadRequest_InvalidTypeName(typeName)); } if (resourceType.ResourceTypeKind == ResourceTypeKind.EntityType) { throw DataServiceException.CreateBadRequestError( Strings.PlainXml_EntityTypeNotSupported(resourceType.FullName)); } } return resourceType; } ///Reads a typed property from the specified XmlReader. /// XmlReader to read from. /// Name of property to read. /// resourceProperty whose value is to be read. ///The instance read, possibly null. private object ReadPropertyWithType(XmlReader reader, string propertyName, ResourceProperty resourceProperty) { Debug.Assert(reader != null, "reader != null"); Debug.Assert(propertyName != null, "propertyName != null"); ResourceType propertyType = null; // If this is a open property OR we do not have to do type conversion for primitive types, // read the type from the payload. bool readTypeFromWire = resourceProperty == null || (!this.Service.Configuration.EnableTypeConversion && resourceProperty.ResourceType.ResourceTypeKind == ResourceTypeKind.Primitive); if (readTypeFromWire) { propertyType = this.ReadOpenPropertyTypeAttribute(reader); } else { propertyType = resourceProperty.ResourceType; } if (this.propertiesApplied != null) { this.propertiesApplied.AddPropertyToTypeMapItem( this.BuildPropertyPath(propertyName), propertyType.FullName); } object propertyValue; String appliedPropertyName = resourceProperty != null ? resourceProperty.Name : propertyName; switch (propertyType.ResourceTypeKind) { case ResourceTypeKind.ComplexType: this.CheckAndIncrementObjectCount(); bool isNull = HasNullAttributeWithTrueValue(reader); if (this.propertiesApplied != null) { this.propertiesApplied.AddAppliedProperty(this.BuildPropertyPath(appliedPropertyName), isNull); } if (isNull) { propertyValue = null; } else { propertyValue = this.Updatable.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(); String savedPath = this.currentPathPrefix; this.currentPathPrefix = String.IsNullOrEmpty(this.currentPathPrefix) ? appliedPropertyName : this.currentPathPrefix + "/" + appliedPropertyName; ApplyContent(propertyReader, propertyType, propertyValue); this.currentPathPrefix = savedPath; } 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); propertyValue = ReadElementString(reader, propertyName); // We need to convert the type to the wire type. Conversion to the property type happens in Deserializer.SetValue method. if (readTypeFromWire) { propertyValue = PlainXmlDeserializer.ConvertValuesForXml(propertyValue, propertyName, propertyType.InstanceType); } if (this.propertiesApplied != null) { this.propertiesApplied.AddAppliedProperty(this.BuildPropertyPath(appliedPropertyName), false); } break; } return propertyValue; } ///Gives an absolute property path based on current prefix /// Name of property ///Absolute path to the property private String BuildPropertyPath(String propertyName) { return String.IsNullOrEmpty(this.currentPathPrefix) ? propertyName : this.currentPathPrefix + "/" + propertyName; } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- FlowDocumentPaginator.cs
- HtmlInputRadioButton.cs
- SemanticAnalyzer.cs
- EntitySqlQueryCacheKey.cs
- PropertyGridCommands.cs
- DocumentViewerBase.cs
- CqlWriter.cs
- ResourceProviderFactory.cs
- OutputCacheSection.cs
- PermissionAttributes.cs
- XmlSecureResolver.cs
- DtrList.cs
- ProtectedProviderSettings.cs
- SqlVersion.cs
- WebServiceHost.cs
- SortedDictionary.cs
- WinEventTracker.cs
- ResourceManagerWrapper.cs
- ComEventsSink.cs
- CodeArrayIndexerExpression.cs
- EncodedStreamFactory.cs
- Grant.cs
- FileDialogPermission.cs
- IApplicationTrustManager.cs
- DSASignatureDeformatter.cs
- AnnotationStore.cs
- GlyphsSerializer.cs
- XmlSchemaNotation.cs
- bidPrivateBase.cs
- DispatchChannelSink.cs
- SetterBaseCollection.cs
- Matrix.cs
- Repeater.cs
- RectKeyFrameCollection.cs
- InvokeHandlers.cs
- NetworkCredential.cs
- SiteMapDataSource.cs
- MappingModelBuildProvider.cs
- OleDbSchemaGuid.cs
- HighContrastHelper.cs
- InkCanvasFeedbackAdorner.cs
- ModuleConfigurationInfo.cs
- DataPager.cs
- ConnectivityStatus.cs
- SchemaCollectionPreprocessor.cs
- LogicalTreeHelper.cs
- SchemaSetCompiler.cs
- ManipulationStartedEventArgs.cs
- CultureTable.cs
- ProtocolViolationException.cs
- TypeForwardedToAttribute.cs
- NetworkInformationPermission.cs
- XhtmlConformanceSection.cs
- _NegotiateClient.cs
- View.cs
- WsdlImporterElementCollection.cs
- DocumentPageHost.cs
- IssuanceTokenProviderBase.cs
- NativeMethods.cs
- Translator.cs
- UTF7Encoding.cs
- SctClaimDictionary.cs
- App.cs
- XPathParser.cs
- DataGridColumnHeadersPresenter.cs
- xdrvalidator.cs
- PathTooLongException.cs
- ToolStripProgressBar.cs
- TemplateControlBuildProvider.cs
- TracePayload.cs
- URLEditor.cs
- SqlDataRecord.cs
- EnvironmentPermission.cs
- SRef.cs
- XMLUtil.cs
- TextEditorTyping.cs
- PageRequestManager.cs
- CharacterShapingProperties.cs
- TraceSwitch.cs
- DynamicActivityXamlReader.cs
- Interfaces.cs
- ClientTargetCollection.cs
- ImportOptions.cs
- ValueTable.cs
- OwnerDrawPropertyBag.cs
- SelectionUIHandler.cs
- List.cs
- ExceptionUtility.cs
- NonVisualControlAttribute.cs
- RectangleGeometry.cs
- Rect3D.cs
- TemplateControlBuildProvider.cs
- EmissiveMaterial.cs
- XmlSerializerNamespaces.cs
- ADMembershipProvider.cs
- FontUnitConverter.cs
- Select.cs
- SafeHandles.cs
- TextTreeInsertElementUndoUnit.cs
- LocationSectionRecord.cs