/// <summary> /// Constructor. /// </summary> /// <param name="atomInputContext">The ATOM input context to read from.</param> protected ODataAtomDeserializer(ODataAtomInputContext atomInputContext) : base(atomInputContext) { Debug.Assert(atomInputContext != null, "atomInputContext != null"); this.atomInputContext = atomInputContext; }
/// <summary> /// Constructor. /// </summary> /// <param name="atomInputContext">The ATOM input context to read from.</param> internal ODataAtomMetadataDeserializer(ODataAtomInputContext atomInputContext) : base(atomInputContext) { XmlNameTable nameTable = this.XmlReader.NameTable; this.EmptyNamespace = nameTable.Add(string.Empty); this.AtomNamespace = nameTable.Add(AtomConstants.AtomNamespace); }
/// <summary> /// Constructor. /// </summary> /// <param name="atomInputContext">The ATOM input context to read from.</param> /// <param name="inSourceElement">Whether this deserializer is reading feed metadata for a source element (true) or a feed element (false).</param> internal ODataAtomFeedMetadataDeserializer(ODataAtomInputContext atomInputContext, bool inSourceElement) : base(atomInputContext) { XmlNameTable nameTable = this.XmlReader.NameTable; this.EmptyNamespace = nameTable.Add(string.Empty); this.InSourceElement = inSourceElement; }
/// <summary> /// Constructor. /// </summary> /// <param name="atomInputContext">The input to read the payload from.</param> /// <param name="expectedItemTypeReference">The expected type reference for the items in the collection.</param> internal ODataAtomCollectionReader(ODataAtomInputContext atomInputContext, IEdmTypeReference expectedItemTypeReference) : base(atomInputContext, expectedItemTypeReference, null /*listener*/) { Debug.Assert(atomInputContext != null, "atomInputContext != null"); this.atomInputContext = atomInputContext; this.atomCollectionDeserializer = new ODataAtomCollectionDeserializer(atomInputContext); }
/// <summary> /// Constructor. /// </summary> /// <param name="atomInputContext">The ATOM input context to read from.</param> internal ODataAtomEntryMetadataDeserializer(ODataAtomInputContext atomInputContext) : base(atomInputContext) { XmlNameTable nameTable = this.XmlReader.NameTable; this.EmptyNamespace = nameTable.Add(string.Empty); this.AtomNamespace = nameTable.Add(AtomConstants.AtomNamespace); }
/// <summary> /// Constructor. /// </summary> /// <param name="atomInputContext">The ATOM input context to read from.</param> internal ODataAtomPropertyAndValueDeserializer(ODataAtomInputContext atomInputContext) : base(atomInputContext) { XmlNameTable nameTable = this.XmlReader.NameTable; this.EmptyNamespace = nameTable.Add(string.Empty); this.ODataNullAttributeName = nameTable.Add(AtomConstants.ODataNullAttributeName); this.ODataCollectionItemElementName = nameTable.Add(AtomConstants.ODataCollectionItemElementName); this.AtomTypeAttributeName = nameTable.Add(AtomConstants.AtomTypeAttributeName); }
private static ODataProperty ReadStringPropertyUnderServerKnob(string payload) { MemoryStream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(payload)); ODataMessageReaderSettings settings = new ODataMessageReaderSettings(); settings.EnableODataServerBehavior(); ODataAtomInputContext context = new ODataAtomInputContext(ODataFormat.Atom, memoryStream, Encoding.UTF8, settings, false /*readingResponse*/, true /*sync*/, EdmModel, null); var deserializer = new ODataAtomPropertyAndValueDeserializer(context); return deserializer.ReadTopLevelProperty(StringProperty, StringProperty.Type); }
/// <summary> /// Constructor. /// </summary> /// <param name="atomInputContext">The ATOM input context to read from.</param> internal ODataAtomEntityReferenceLinkDeserializer(ODataAtomInputContext atomInputContext) : base(atomInputContext) { XmlNameTable nameTable = this.XmlReader.NameTable; this.ODataFeedElementName = nameTable.Add(AtomConstants.AtomFeedElementName); this.ODataCountElementName = nameTable.Add(AtomConstants.ODataCountElementName); this.ODataNextElementName = nameTable.Add(AtomConstants.ODataNextLinkElementName); this.ODataRefElementName = nameTable.Add(AtomConstants.ODataRefElementName); }
/// <summary> /// Constructor. /// </summary> /// <param name="atomInputContext">The ATOM input context to read from.</param> internal ODataAtomServiceDocumentMetadataDeserializer(ODataAtomInputContext atomInputContext) : base(atomInputContext) { XmlNameTable nameTable = this.XmlReader.NameTable; this.AtomNamespace = nameTable.Add(AtomConstants.AtomNamespace); this.AtomCategoryElementName = nameTable.Add(AtomConstants.AtomCategoryElementName); this.AtomHRefAttributeName = nameTable.Add(AtomConstants.AtomHRefAttributeName); this.AtomPublishingFixedAttributeName = nameTable.Add(AtomConstants.AtomPublishingFixedAttributeName); this.AtomCategorySchemeAttributeName = nameTable.Add(AtomConstants.AtomCategorySchemeAttributeName); this.AtomCategoryTermAttributeName = nameTable.Add(AtomConstants.AtomCategoryTermAttributeName); this.AtomCategoryLabelAttributeName = nameTable.Add(AtomConstants.AtomCategoryLabelAttributeName); this.EmptyNamespace = nameTable.Add(string.Empty); }
/// <summary> /// Constructor. /// </summary> /// <param name="atomInputContext">The input to read the payload from.</param> /// <param name="navigationSource">The navigation source we are going to read entities for.</param> /// <param name="expectedEntityType">The expected entity type for the entry to be read (in case of entry reader) or entries in the feed to be read (in case of feed reader).</param> /// <param name="readingFeed">true if the reader is created for reading a feed; false when it is created for reading an entry.</param> internal ODataAtomReader( ODataAtomInputContext atomInputContext, IEdmNavigationSource navigationSource, IEdmEntityType expectedEntityType, bool readingFeed) : base(atomInputContext, readingFeed, false /*readingDelta*/, null /*listener*/) { Debug.Assert(atomInputContext != null, "atomInputContext != null"); Debug.Assert( expectedEntityType == null || atomInputContext.Model.IsUserModel(), "If the expected type is specified we need model as well. We should have verified that by now."); this.atomInputContext = atomInputContext; this.atomEntryAndFeedDeserializer = new ODataAtomEntryAndFeedDeserializer(atomInputContext); this.EnterScope(new Scope(ODataReaderState.Start, /*item*/ null, navigationSource, expectedEntityType, /*contextUri*/null)); }
/// <summary> /// Detects the payload kind(s) from the message stream. /// </summary> /// <param name="messageStream">The message stream to read from for payload kind detection.</param> /// <param name="readingResponse">true if reading a response message; otherwise false.</param> /// <param name="synchronous">true if the input should be read synchronously; false if it should be read asynchronously.</param> /// <param name="detectionInfo">Additional information available for the payload kind detection.</param> /// <returns>An enumerable of zero or more payload kinds depending on what payload kinds were detected.</returns> private IEnumerable <ODataPayloadKind> DetectPayloadKindImplementation( Stream messageStream, bool readingResponse, bool synchronous, ODataPayloadKindDetectionInfo detectionInfo) { using (ODataAtomInputContext inputContext = new ODataAtomInputContext( this, messageStream, detectionInfo.GetEncoding(), detectionInfo.MessageReaderSettings, readingResponse, synchronous, detectionInfo.Model, /*urlResolver*/ null)) { return(inputContext.DetectPayloadKind(detectionInfo)); } }
/// <summary> /// Creates a new ATOM annotation parser. /// </summary> /// <param name="inputContext">The input context this annotation reader should use to read annotation elements.</param> /// <param name="propertyAndValueDeserializer">The property and value deserializer to use to read the value of an annotation element.</param> internal ODataAtomAnnotationReader(ODataAtomInputContext inputContext, ODataAtomPropertyAndValueDeserializer propertyAndValueDeserializer) { this.inputContext = inputContext; this.propertyAndValueDeserializer = propertyAndValueDeserializer; BufferingXmlReader xmlReader = this.inputContext.XmlReader; Debug.Assert(xmlReader != null, "xmlReader != null"); Debug.Assert(xmlReader.NameTable != null, "xmlReader.NameTable != null"); xmlReader.NameTable.Add(AtomConstants.ODataAnnotationTargetAttribute); xmlReader.NameTable.Add(AtomConstants.ODataAnnotationTermAttribute); xmlReader.NameTable.Add(AtomConstants.AtomTypeAttributeName); xmlReader.NameTable.Add(AtomConstants.ODataNullAttributeName); xmlReader.NameTable.Add(AtomConstants.ODataAnnotationStringAttribute); xmlReader.NameTable.Add(AtomConstants.ODataAnnotationBoolAttribute); xmlReader.NameTable.Add(AtomConstants.ODataAnnotationDecimalAttribute); xmlReader.NameTable.Add(AtomConstants.ODataAnnotationIntAttribute); xmlReader.NameTable.Add(AtomConstants.ODataAnnotationFloatAttribute); this.odataMetadataNamespace = xmlReader.NameTable.Add(AtomConstants.ODataMetadataNamespace); this.attributeElementName = xmlReader.NameTable.Add(AtomConstants.ODataAnnotationElementName); }
/// <summary> /// Detects the payload kind(s) from the message stream. /// </summary> /// <param name="messageStream">The message stream to read from for payload kind detection.</param> /// <param name="readingResponse">true if reading a response message; otherwise false.</param> /// <param name="synchronous">true if the input should be read synchronously; false if it should be read asynchronously.</param> /// <param name="detectionInfo">Additional information available for the payload kind detection.</param> /// <returns>An enumerable of zero or more payload kinds depending on what payload kinds were detected.</returns> private IEnumerable <ODataPayloadKind> DetectPayloadKindImplementation( Stream messageStream, bool readingResponse, bool synchronous, ODataPayloadKindDetectionInfo detectionInfo) { using (ODataAtomInputContext inputContext = new ODataAtomInputContext( this, messageStream, detectionInfo.GetEncoding(), detectionInfo.MessageReaderSettings, ODataVersion.V4, // NOTE: we don't rely on the version for payload kind detection; taking the latest. readingResponse, synchronous, detectionInfo.Model, /*urlResolver*/ null)) { return(inputContext.DetectPayloadKind(detectionInfo)); } }
/// <summary> /// Constructor. /// </summary> /// <param name="atomInputContext">The ATOM input context to read from.</param> internal ODataAtomServiceDocumentDeserializer(ODataAtomInputContext atomInputContext) : base(atomInputContext) { XmlNameTable nameTable = this.XmlReader.NameTable; this.AtomPublishingServiceElementName = nameTable.Add(AtomConstants.AtomPublishingServiceElementName); this.AtomPublishingWorkspaceElementName = nameTable.Add(AtomConstants.AtomPublishingWorkspaceElementName); this.AtomPublishingCollectionElementName = nameTable.Add(AtomConstants.AtomPublishingCollectionElementName); this.AtomPublishingAcceptElementName = nameTable.Add(AtomConstants.AtomPublishingAcceptElementName); this.AtomPublishingCategoriesElementName = nameTable.Add(AtomConstants.AtomPublishingCategoriesElementName); this.AtomHRefAttributeName = nameTable.Add(AtomConstants.AtomHRefAttributeName); this.AtomPublishingNamespace = nameTable.Add(AtomConstants.AtomPublishingNamespace); this.AtomNamespace = nameTable.Add(AtomConstants.AtomNamespace); this.AtomTitleElementName = nameTable.Add(AtomConstants.AtomTitleElementName); this.EmptyNamespace = nameTable.Add(string.Empty); this.ODataMetadataNamespace = nameTable.Add(AtomConstants.ODataMetadataNamespace); this.ODataFunctionImportElementName = nameTable.Add(AtomConstants.AtomServiceDocumentFunctionImportElementName); this.ODataSingletonElementName = nameTable.Add(AtomConstants.AtomServiceDocumentSingletonElementName); this.ODataNameAttribute = nameTable.Add(AtomConstants.ODataNameAttribute); }
private void VerifyTypeCollectionRoundtrip(ODataCollectionValue value, string propertyName, ODataFeedAndEntrySerializationInfo info) { var properties = new[] { new ODataProperty { Name = propertyName, Value = value } }; var entry = new ODataEntry() { TypeName = "NS.Student", Properties = properties, SerializationInfo = info}; MemoryStream stream = new MemoryStream(); using (ODataAtomOutputContext outputContext = new ODataAtomOutputContext( ODataFormat.Atom, new NonDisposingStream(stream), Encoding.UTF8, new ODataMessageWriterSettings() { Version = ODataVersion.V4 }, /*writingResponse*/ true, /*synchronous*/ true, model, /*urlResolver*/ null)) { outputContext.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri); var atomWriter = new ODataAtomWriter(outputContext, /*entitySet*/ null, /*entityType*/ null, /*writingFeed*/ false); atomWriter.WriteStart(entry); atomWriter.WriteEnd(); } stream.Position = 0; object actualValue = null; using (ODataAtomInputContext inputContext = new ODataAtomInputContext( ODataFormat.Atom, stream, Encoding.UTF8, new ODataMessageReaderSettings(), /*readingResponse*/ true, /*synchronous*/ true, model, /*urlResolver*/ null)) { var atomReader = new ODataAtomReader(inputContext, /*entitySet*/ null, /*entityType*/ null, /*writingFeed*/ false); while (atomReader.Read()) { if (atomReader.State == ODataReaderState.EntryEnd) { ODataEntry entryOut = atomReader.Item as ODataEntry; actualValue = entryOut.Properties.Single(p => p.Name == propertyName).ODataValue; } } } TestUtils.AssertODataValueAreEqual(actualValue as ODataValue, value); }
/// <summary> /// Constructor. /// </summary> /// <param name="atomInputContext">The ATOM input context to read from.</param> internal ODataAtomErrorDeserializer(ODataAtomInputContext atomInputContext) : base(atomInputContext) { }
/// <summary> /// Constructor. /// </summary> /// <param name="atomInputContext">The ATOM input context to read from.</param> internal ODataAtomEntryAndFeedDeserializer(ODataAtomInputContext atomInputContext) : base(atomInputContext) { XmlNameTable nameTable = this.XmlReader.NameTable; this.AtomNamespace = nameTable.Add(AtomConstants.AtomNamespace); this.AtomEntryElementName = nameTable.Add(AtomConstants.AtomEntryElementName); this.AtomCategoryElementName = nameTable.Add(AtomConstants.AtomCategoryElementName); this.AtomCategoryTermAttributeName = nameTable.Add(AtomConstants.AtomCategoryTermAttributeName); this.AtomCategorySchemeAttributeName = nameTable.Add(AtomConstants.AtomCategorySchemeAttributeName); this.AtomContentElementName = nameTable.Add(AtomConstants.AtomContentElementName); this.AtomLinkElementName = nameTable.Add(AtomConstants.AtomLinkElementName); this.AtomPropertiesElementName = nameTable.Add(AtomConstants.AtomPropertiesElementName); this.AtomFeedElementName = nameTable.Add(AtomConstants.AtomFeedElementName); this.AtomIdElementName = nameTable.Add(AtomConstants.AtomIdElementName); this.AtomLinkRelationAttributeName = nameTable.Add(AtomConstants.AtomLinkRelationAttributeName); this.AtomLinkHrefAttributeName = nameTable.Add(AtomConstants.AtomLinkHrefAttributeName); this.MediaLinkEntryContentSourceAttributeName = nameTable.Add(AtomConstants.MediaLinkEntryContentSourceAttributeName); this.ODataETagAttributeName = nameTable.Add(AtomConstants.ODataETagAttributeName); this.ODataCountElementName = nameTable.Add(AtomConstants.ODataCountElementName); this.ODataInlineElementName = nameTable.Add(AtomConstants.ODataInlineElementName); this.ODataActionElementName = nameTable.Add(AtomConstants.ODataActionElementName); this.ODataFunctionElementName = nameTable.Add(AtomConstants.ODataFunctionElementName); this.ODataOperationMetadataAttribute = nameTable.Add(AtomConstants.ODataOperationMetadataAttribute); this.ODataOperationTitleAttribute = nameTable.Add(AtomConstants.ODataOperationTitleAttribute); this.ODataOperationTargetAttribute = nameTable.Add(AtomConstants.ODataOperationTargetAttribute); this.atomAnnotationReader = new ODataAtomAnnotationReader(this.AtomInputContext, this); }
/// <summary> /// Constructor. /// </summary> /// <param name="atomInputContext">The ATOM input context to read from.</param> internal ODataAtomPayloadKindDetectionDeserializer(ODataAtomInputContext atomInputContext) : base(atomInputContext) { }
private void VerifyPrimitiveValueRoundtrips(object clrValue, string edmTypeName, ODataVersion version, string description) { IEdmModel model = new EdmModel(); IEdmPrimitiveTypeReference typeReference = new EdmPrimitiveTypeReference((IEdmPrimitiveType)model.FindType(edmTypeName), true); MemoryStream stream = new MemoryStream(); using (ODataAtomOutputContext outputContext = new ODataAtomOutputContext( ODataFormat.Atom, new NonDisposingStream(stream), Encoding.UTF8, new ODataMessageWriterSettings() { Version = version }, /*writingResponse*/ true, /*synchronous*/ true, model, /*urlResolver*/ null)) { ODataAtomPropertyAndValueSerializer serializer = new ODataAtomPropertyAndValueSerializer(outputContext); serializer.XmlWriter.WriteStartElement("ValueElement"); serializer.WritePrimitiveValue( clrValue, /*collectionValidator*/ null, typeReference, /*serializationTypeNameAnnotation*/ null); serializer.XmlWriter.WriteEndElement(); } stream.Position = 0; object actualValue; using (ODataAtomInputContext inputContext = new ODataAtomInputContext( ODataFormat.Atom, stream, Encoding.UTF8, new ODataMessageReaderSettings(), /*readingResponse*/ true, /*synchronous*/ true, model, /*urlResolver*/ null)) { ODataAtomPropertyAndValueDeserializer deserializer = new ODataAtomPropertyAndValueDeserializer(inputContext); deserializer.XmlReader.MoveToContent(); actualValue = deserializer.ReadNonEntityValue( typeReference, /*duplicatePropertyNamesChecker*/ null, /*collectionValidator*/ null, /*validateNullValue*/ true); } if (clrValue is byte[]) { ((byte[])actualValue).Should().Equal((byte[])clrValue, description); } else { actualValue.Should().Be(clrValue, description); } }
/// <summary> /// Creates a new instance of this class by consuming xml from the given input context. /// </summary> /// <param name="inputContext">The input context to use to create the annotation.</param> /// <param name="propertyAndValueDeserializer">The property and value deserializer to use when reading values in the annotation element content.</param> /// <returns>The <see cref="AtomInstanceAnnotation"/> populated with the information from the 'm:annotation' XML element, as long as the value is a string. Returns null otherwise.</returns> /// <remarks> /// Pre-Condition: XmlNodeType.Element - The annotation element to read. /// Post-Condition: XmlNodeType.Any - The node after the end of the annotation element, or the same element as in the pre-condition if the annotation was skipped. /// </remarks> internal static AtomInstanceAnnotation CreateFrom(ODataAtomInputContext inputContext, ODataAtomPropertyAndValueDeserializer propertyAndValueDeserializer) { var xmlReader = inputContext.XmlReader; Debug.Assert(xmlReader != null, "xmlReader != null"); Debug.Assert(xmlReader.NodeType == XmlNodeType.Element, "xmlReader must be positioned on an Element"); Debug.Assert(xmlReader.NameTable != null, "xmlReader.NameTable != null"); Debug.Assert(xmlReader.LocalName == "annotation", "Must be positioned on an annotation element"); string termAttributeValue = null; string targetAttributeValue = null; string typeAttributeValue = null; bool nullAttributePresentAndTrue = false; bool sawMultipleAttributeValueNotations = false; // Notes on "attribute value notation": // Empty elements may have the annotation value specified via an attribute on the annotation element. // Exactly one of the following attributes must be present if this notation is being used: "string", "int", "bool", "float", "decimal". // The value of the annotation is the value of this value-specifying attribute. string attributeValueNotationAttributeName = null; string attributeValueNotationAttributeValue = null; IEdmPrimitiveTypeReference attributeValueNotationTypeReference = null; XmlNameTable xmlNameTable = xmlReader.NameTable; string metadataNamespace = xmlNameTable.Get(AtomConstants.ODataMetadataNamespace); string nullAttributeName = xmlNameTable.Get(AtomConstants.ODataNullAttributeName); string typeAttributeName = xmlNameTable.Get(AtomConstants.AtomTypeAttributeName); string emptyNamespace = xmlNameTable.Get(string.Empty); string termAttributeName = xmlNameTable.Get(AtomConstants.ODataAnnotationTermAttribute); string targetAttributeName = xmlNameTable.Get(AtomConstants.ODataAnnotationTargetAttribute); // Loop through all the attributes and remember the ones specific to annotations. while (xmlReader.MoveToNextAttribute()) { if (xmlReader.NamespaceEquals(metadataNamespace)) { if (xmlReader.LocalNameEquals(typeAttributeName)) { typeAttributeValue = xmlReader.Value; } else if (xmlReader.LocalNameEquals(nullAttributeName)) { nullAttributePresentAndTrue = ODataAtomReaderUtils.ReadMetadataNullAttributeValue(xmlReader.Value); } // Ignore all other attributes in the metadata namespace. // In general, we only fail on reading if we can't make sense of the document any more. Reader should be loose. // If we choose to start recognizing an additional attribute in the metadata namespace later, be careful not to // fail if it doesn't parse correctly (so that we don't cause a breaking change). } else if (xmlReader.NamespaceEquals(emptyNamespace)) { if (xmlReader.LocalNameEquals(termAttributeName)) { termAttributeValue = xmlReader.Value; // Before doing any other validation or further reading, check whether or not to read this annotation according to the filter. if (propertyAndValueDeserializer.MessageReaderSettings.ShouldSkipAnnotation(termAttributeValue)) { xmlReader.MoveToElement(); return null; } } else if (xmlReader.LocalNameEquals(targetAttributeName)) { targetAttributeValue = xmlReader.Value; } else { // Check if this attribute is one used by attribute value notation. IEdmPrimitiveTypeReference potentialTypeFromAttributeValueNotation = LookupEdmTypeByAttributeValueNotationName(xmlReader.LocalName); if (potentialTypeFromAttributeValueNotation != null) { // If we've already seen an attribute used for attribute value notation, // throw since we don't know which type to use (even if the values are the same). // But don't throw yet, because we might not have encountered the term name yet, // and the annotation filter might say to ignore this annotation (and so we shouldn't throw). if (attributeValueNotationTypeReference != null) { sawMultipleAttributeValueNotations = true; } attributeValueNotationTypeReference = potentialTypeFromAttributeValueNotation; attributeValueNotationAttributeName = xmlReader.LocalName; attributeValueNotationAttributeValue = xmlReader.Value; } } // Ignore all other attributes in the empty namespace. } // Ignore all other attributes in all other namespaces. } xmlReader.MoveToElement(); // The term attribute is required. if (termAttributeValue == null) { throw new ODataException(ODataErrorStrings.AtomInstanceAnnotation_MissingTermAttributeOnAnnotationElement); } if (sawMultipleAttributeValueNotations) { throw new ODataException(ODataErrorStrings.AtomInstanceAnnotation_MultipleAttributeValueNotationAttributes); } // If this term is defined in the model, look up its type. If the term is not in the model, this will be null. IEdmTypeReference expectedTypeReference = MetadataUtils.LookupTypeOfValueTerm(termAttributeValue, propertyAndValueDeserializer.Model); ODataValue annotationValue; if (nullAttributePresentAndTrue) { // The m:null attribute has precedence over the content of the element, thus if we find m:null='true' we ignore the content of the element. ReaderValidationUtils.ValidateNullValue( propertyAndValueDeserializer.Model, expectedTypeReference, propertyAndValueDeserializer.MessageReaderSettings, /*validateNullValue*/ true, termAttributeValue); annotationValue = new ODataNullValue(); } else if (attributeValueNotationTypeReference != null) { annotationValue = GetValueFromAttributeValueNotation( expectedTypeReference, attributeValueNotationTypeReference, attributeValueNotationAttributeName, attributeValueNotationAttributeValue, typeAttributeValue, xmlReader.IsEmptyElement, propertyAndValueDeserializer.Model, propertyAndValueDeserializer.MessageReaderSettings); } else { annotationValue = ReadValueFromElementContent(propertyAndValueDeserializer, expectedTypeReference); } // Read the end tag (or the start tag if it was an empty element). xmlReader.Read(); return new AtomInstanceAnnotation( targetAttributeValue, termAttributeValue, annotationValue); }
/// <summary> /// Detects the payload kind(s) from the message stream. /// </summary> /// <param name="messageStream">The message stream to read from for payload kind detection.</param> /// <param name="readingResponse">true if reading a response message; otherwise false.</param> /// <param name="synchronous">true if the input should be read synchronously; false if it should be read asynchronously.</param> /// <param name="detectionInfo">Additional information available for the payload kind detection.</param> /// <returns>An enumerable of zero or more payload kinds depending on what payload kinds were detected.</returns> private IEnumerable<ODataPayloadKind> DetectPayloadKindImplementation( Stream messageStream, bool readingResponse, bool synchronous, ODataPayloadKindDetectionInfo detectionInfo) { using (ODataAtomInputContext inputContext = new ODataAtomInputContext( this, messageStream, detectionInfo.GetEncoding(), detectionInfo.MessageReaderSettings, readingResponse, synchronous, detectionInfo.Model, /*urlResolver*/ null)) { return inputContext.DetectPayloadKind(detectionInfo); } }
/// <summary> /// Constructor. /// </summary> /// <param name="atomInputContext">The ATOM input context to read from.</param> internal ODataAtomCollectionDeserializer(ODataAtomInputContext atomInputContext) : base(atomInputContext) { this.duplicatePropertyNamesChecker = this.CreateDuplicatePropertyNamesChecker(); }
private void VerifyComplexTypeRoundtrip(ODataComplexValue value, string typeName) { var typeReference = new EdmComplexTypeReference((IEdmComplexType)model.FindType(typeName), true); MemoryStream stream = new MemoryStream(); using (ODataAtomOutputContext outputContext = new ODataAtomOutputContext( ODataFormat.Atom, new NonDisposingStream(stream), Encoding.UTF8, new ODataMessageWriterSettings() { Version = ODataVersion.V4 }, /*writingResponse*/ true, /*synchronous*/ true, model, /*urlResolver*/ null)) { ODataAtomPropertyAndValueSerializer serializer = new ODataAtomPropertyAndValueSerializer(outputContext); serializer.XmlWriter.WriteStartElement("ValueElement"); serializer.WriteComplexValue( value, typeReference, /*isOpenPropertyType*/ false, /*isWritingCollection*/ false, /*beforeValueAction*/ null, /*afterValueAction*/ null, new DuplicatePropertyNamesChecker(false, false), /*collectionValidator*/ null, /*projectedProperties*/ null); serializer.XmlWriter.WriteEndElement(); } stream.Position = 0; object actualValue; using (ODataAtomInputContext inputContext = new ODataAtomInputContext( ODataFormat.Atom, stream, Encoding.UTF8, new ODataMessageReaderSettings(), /*readingResponse*/ true, /*synchronous*/ true, model, /*urlResolver*/ null)) { ODataAtomPropertyAndValueDeserializer deserializer = new ODataAtomPropertyAndValueDeserializer(inputContext); deserializer.XmlReader.MoveToContent(); actualValue = deserializer.ReadNonEntityValue( typeReference, /*duplicatePropertyNamesChecker*/ null, /*collectionValidator*/ null, /*validateNullValue*/ true); } TestUtils.AssertODataValueAreEqual(actualValue as ODataValue, value); }
private ODataAtomAnnotationReader CreateODataAtomAnnotationReader(string annotationElementText) { // Create a dummy root node wrapping the annotation element in order to define the namespace prefix mappings. string xmlText = "<dummy xmlns:m=\"" + AtomConstants.ODataMetadataNamespace + "\" xmlns:d=\"" + AtomConstants.ODataNamespace + "\" xmlns=\"" + AtomConstants.AtomNamespace + "\">" + annotationElementText + "</dummy>"; var inputContext = new ODataAtomInputContext( ODataFormat.Atom, new MemoryStream(Encoding.UTF8.GetBytes(xmlText)), Encoding.UTF8, new ODataMessageReaderSettings { ShouldIncludeAnnotation = this.shouldIncludeAnnotation }, true, true, this.model, null); this.xmlReader = inputContext.XmlReader; var parser = new ODataAtomAnnotationReader(inputContext, new ODataAtomPropertyAndValueDeserializer(inputContext)); // Position the xml reader on the dummy element. this.xmlReader.Read(); // Read over the start element of the dummy element (and position the reader on the m:annotation start tag). this.xmlReader.Read(); return parser; }
/// <summary> /// Creates a new instance of this class by consuming xml from the given input context. /// </summary> /// <param name="inputContext">The input context to use to create the annotation.</param> /// <param name="propertyAndValueDeserializer">The property and value deserializer to use when reading values in the annotation element content.</param> /// <returns>The <see cref="AtomInstanceAnnotation"/> populated with the information from the 'm:annotation' XML element, as long as the value is a string. Returns null otherwise.</returns> /// <remarks> /// Pre-Condition: XmlNodeType.Element - The annotation element to read. /// Post-Condition: XmlNodeType.Any - The node after the end of the annotation element, or the same element as in the pre-condition if the annotation was skipped. /// </remarks> internal static AtomInstanceAnnotation CreateFrom(ODataAtomInputContext inputContext, ODataAtomPropertyAndValueDeserializer propertyAndValueDeserializer) { var xmlReader = inputContext.XmlReader; Debug.Assert(xmlReader != null, "xmlReader != null"); Debug.Assert(xmlReader.NodeType == XmlNodeType.Element, "xmlReader must be positioned on an Element"); Debug.Assert(xmlReader.NameTable != null, "xmlReader.NameTable != null"); Debug.Assert(xmlReader.LocalName == "annotation", "Must be positioned on an annotation element"); string termAttributeValue = null; string targetAttributeValue = null; string typeAttributeValue = null; bool nullAttributePresentAndTrue = false; bool sawMultipleAttributeValueNotations = false; // Notes on "attribute value notation": // Empty elements may have the annotation value specified via an attribute on the annotation element. // Exactly one of the following attributes must be present if this notation is being used: "string", "int", "bool", "float", "decimal". // The value of the annotation is the value of this value-specifying attribute. string attributeValueNotationAttributeName = null; string attributeValueNotationAttributeValue = null; IEdmPrimitiveTypeReference attributeValueNotationTypeReference = null; XmlNameTable xmlNameTable = xmlReader.NameTable; string metadataNamespace = xmlNameTable.Get(AtomConstants.ODataMetadataNamespace); string nullAttributeName = xmlNameTable.Get(AtomConstants.ODataNullAttributeName); string typeAttributeName = xmlNameTable.Get(AtomConstants.AtomTypeAttributeName); string emptyNamespace = xmlNameTable.Get(string.Empty); string termAttributeName = xmlNameTable.Get(AtomConstants.ODataAnnotationTermAttribute); string targetAttributeName = xmlNameTable.Get(AtomConstants.ODataAnnotationTargetAttribute); // Loop through all the attributes and remember the ones specific to annotations. while (xmlReader.MoveToNextAttribute()) { if (xmlReader.NamespaceEquals(metadataNamespace)) { if (xmlReader.LocalNameEquals(typeAttributeName)) { typeAttributeValue = xmlReader.Value; } else if (xmlReader.LocalNameEquals(nullAttributeName)) { nullAttributePresentAndTrue = ODataAtomReaderUtils.ReadMetadataNullAttributeValue(xmlReader.Value); } // Ignore all other attributes in the metadata namespace. // In general, we only fail on reading if we can't make sense of the document any more. Reader should be loose. // If we choose to start recognizing an additional attribute in the metadata namespace later, be careful not to // fail if it doesn't parse correctly (so that we don't cause a breaking change). } else if (xmlReader.NamespaceEquals(emptyNamespace)) { if (xmlReader.LocalNameEquals(termAttributeName)) { termAttributeValue = xmlReader.Value; // Before doing any other validation or further reading, check whether or not to read this annotation according to the filter. if (propertyAndValueDeserializer.MessageReaderSettings.ShouldSkipAnnotation(termAttributeValue)) { xmlReader.MoveToElement(); return(null); } } else if (xmlReader.LocalNameEquals(targetAttributeName)) { targetAttributeValue = xmlReader.Value; } else { // Check if this attribute is one used by attribute value notation. IEdmPrimitiveTypeReference potentialTypeFromAttributeValueNotation = LookupEdmTypeByAttributeValueNotationName(xmlReader.LocalName); if (potentialTypeFromAttributeValueNotation != null) { // If we've already seen an attribute used for attribute value notation, // throw since we don't know which type to use (even if the values are the same). // But don't throw yet, because we might not have encountered the term name yet, // and the annotation filter might say to ignore this annotation (and so we shouldn't throw). if (attributeValueNotationTypeReference != null) { sawMultipleAttributeValueNotations = true; } attributeValueNotationTypeReference = potentialTypeFromAttributeValueNotation; attributeValueNotationAttributeName = xmlReader.LocalName; attributeValueNotationAttributeValue = xmlReader.Value; } } // Ignore all other attributes in the empty namespace. } // Ignore all other attributes in all other namespaces. } xmlReader.MoveToElement(); // The term attribute is required. if (termAttributeValue == null) { throw new ODataException(ODataErrorStrings.AtomInstanceAnnotation_MissingTermAttributeOnAnnotationElement); } if (sawMultipleAttributeValueNotations) { throw new ODataException(ODataErrorStrings.AtomInstanceAnnotation_MultipleAttributeValueNotationAttributes); } // If this term is defined in the model, look up its type. If the term is not in the model, this will be null. IEdmTypeReference expectedTypeReference = MetadataUtils.LookupTypeOfValueTerm(termAttributeValue, propertyAndValueDeserializer.Model); ODataValue annotationValue; if (nullAttributePresentAndTrue) { // The m:null attribute has precedence over the content of the element, thus if we find m:null='true' we ignore the content of the element. ReaderValidationUtils.ValidateNullValue( propertyAndValueDeserializer.Model, expectedTypeReference, propertyAndValueDeserializer.MessageReaderSettings, /*validateNullValue*/ true, termAttributeValue); annotationValue = new ODataNullValue(); } else if (attributeValueNotationTypeReference != null) { annotationValue = GetValueFromAttributeValueNotation( expectedTypeReference, attributeValueNotationTypeReference, attributeValueNotationAttributeName, attributeValueNotationAttributeValue, typeAttributeValue, xmlReader.IsEmptyElement, propertyAndValueDeserializer.Model, propertyAndValueDeserializer.MessageReaderSettings); } else { annotationValue = ReadValueFromElementContent(propertyAndValueDeserializer, expectedTypeReference); } // Read the end tag (or the start tag if it was an empty element). xmlReader.Read(); return(new AtomInstanceAnnotation( targetAttributeValue, termAttributeValue, annotationValue)); }
private ODataAtomServiceDocumentDeserializer CreateODataAtomServiceDocumentDeserializer(MemoryStream stream, bool enableAtomMetadataReading, IODataUrlResolver urlResolver = null) { ODataMessageReaderSettings settings = new ODataMessageReaderSettings(); settings.EnableAtomMetadataReading = enableAtomMetadataReading; ODataAtomInputContext inputContext = new ODataAtomInputContext(ODataFormat.Atom, stream, Encoding.UTF8, settings, true /*readingResponse*/, true /*sync*/, null /*edmModel*/, urlResolver); return new ODataAtomServiceDocumentDeserializer(inputContext); }