Ejemplo n.º 1
0
 /// <summary>
 /// Validates a stream reference property.
 /// </summary>
 /// <param name="streamProperty">The stream property to check.</param>
 /// <param name="structuredType">The owning type of the stream property or null if no metadata is available.</param>
 /// <param name="streamEdmProperty">The stream property defined by the model.</param>
 public void ValidateStreamReferenceProperty(ODataProperty streamProperty,
                                             IEdmStructuredType structuredType,
                                             IEdmProperty streamEdmProperty)
 {
     ReaderValidationUtils.ValidateStreamReferenceProperty(
         streamProperty, structuredType, streamEdmProperty, settings.ThrowOnUndeclaredPropertyForNonOpenType);
 }
Ejemplo n.º 2
0
        private ODataEntityReferenceLink ReadSingleEntityReferenceLink()
        {
            if (base.JsonReader.NodeType != JsonNodeType.StartObject)
            {
                throw new ODataException(Strings.ODataJsonEntityReferenceLinkDeserializer_EntityReferenceLinkMustBeObjectValue(base.JsonReader.NodeType));
            }
            base.JsonReader.ReadStartObject();
            ODataEntityReferenceLink link = new ODataEntityReferenceLink();

            while (base.JsonReader.NodeType == JsonNodeType.Property)
            {
                string strB = base.JsonReader.ReadPropertyName();
                if (string.CompareOrdinal("uri", strB) == 0)
                {
                    if (link.Url != null)
                    {
                        throw new ODataException(Strings.ODataJsonEntityReferenceLinkDeserializer_MultipleUriPropertiesInEntityReferenceLink);
                    }
                    string uriFromPayload = base.JsonReader.ReadStringValue("uri");
                    if (uriFromPayload == null)
                    {
                        throw new ODataException(Strings.ODataJsonEntityReferenceLinkDeserializer_EntityReferenceLinkUriCannotBeNull);
                    }
                    link.Url = base.ProcessUriFromPayload(uriFromPayload);
                }
                else
                {
                    base.JsonReader.SkipValue();
                }
            }
            ReaderValidationUtils.ValidateEntityReferenceLink(link);
            base.JsonReader.ReadEndObject();
            return(link);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Asynchronous implementation of the collection reader logic when in state 'Start'.
        /// </summary>
        /// <param name="propertyAndAnnotationCollector">The duplicate property names checker for the top-level scope.</param>
        /// <returns>
        /// A task that represents the asynchronous read operation.
        /// The value of the TResult parameter contains true if more items can be read from the reader; otherwise false.
        /// </returns>
        /// <remarks>
        /// Pre-Condition:  JsonNodeType.None:      assumes that the JSON reader has not been used yet when not reading a nested payload.
        /// Post-Condition: The reader is positioned on the first node of the first item or the EndArray node of an empty item array
        /// </remarks>
        private async Task <bool> ReadAtStartImplementationAsynchronously(PropertyAndAnnotationCollector propertyAndAnnotationCollector)
        {
            Debug.Assert(propertyAndAnnotationCollector != null, "propertyAndAnnotationCollector != null");

            IEdmTypeReference actualItemTypeReference;

            this.ExpectedItemTypeReference = ReaderValidationUtils.ValidateCollectionContextUriAndGetPayloadItemTypeReference(
                this.jsonLightCollectionDeserializer.ContextUriParseResult,
                this.ExpectedItemTypeReference);

            // Read the start of the collection until we find the content array for top-level collections
            Tuple <ODataCollectionStart, IEdmTypeReference> readCollectionStartResult = await this.jsonLightCollectionDeserializer.ReadCollectionStartAsync(
                propertyAndAnnotationCollector,
                this.IsReadingNestedPayload,
                this.ExpectedItemTypeReference).ConfigureAwait(false);

            ODataCollectionStart collectionStart = readCollectionStartResult.Item1;

            actualItemTypeReference = readCollectionStartResult.Item2;

            if (actualItemTypeReference != null)
            {
                this.ExpectedItemTypeReference = actualItemTypeReference;
            }

            await this.jsonLightCollectionDeserializer.JsonReader.ReadStartArrayAsync()
            .ConfigureAwait(false);

            this.EnterScope(ODataCollectionReaderState.CollectionStart, collectionStart);

            return(true);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Reads the headers of a part.
        /// </summary>
        /// <param name="contentId">Content-ID read from changeset header, null if changeset part detected</param>
        /// <returns>true if the start of a changeset part was detected; otherwise false.</returns>
        internal bool ProcessPartHeader(out string contentId)
        {
            Debug.Assert(this.batchEncoding != null, "Batch encoding should have been established on first call to SkipToBoundary.");

            bool isChangeSetPart;
            ODataBatchOperationHeaders headers = this.ReadPartHeaders(out isChangeSetPart);

            contentId = null;

            if (isChangeSetPart)
            {
                // determine the changeset boundary and the changeset encoding from the content type header
                this.DetermineChangesetBoundaryAndEncoding(headers[ODataConstants.ContentTypeHeader]);

                if (this.changesetEncoding == null)
                {
                    // NOTE: No changeset encoding was specified in the changeset's content type header.
                    //       Determine the changeset encoding from the first bytes in the changeset.
                    // NOTE: We do not have to skip over the potential preamble of the encoding
                    //       because the batch reader will skip over everything (incl. the preamble)
                    //       until it finds the first changeset (or batch) boundary
                    this.changesetEncoding = this.DetectEncoding();
                }

                // Verify that we only allow single byte encodings and UTF-8 for now.
                ReaderValidationUtils.ValidateEncodingSupportedInBatch(this.changesetEncoding);
            }
            else if (this.ChangeSetBoundary != null)
            {
                headers.TryGetValue(ODataConstants.ContentIdHeader, out contentId);
            }

            return(isChangeSetPart);
        }
Ejemplo n.º 5
0
        internal static object ConvertValue(
            object value,
            IEdmPrimitiveTypeReference primitiveTypeReference,
            ODataMessageReaderSettings messageReaderSettings,
            bool validateNullValue,
            string propertyName,
            ODataPayloadValueConverter converter)
        {
            Debug.Assert(primitiveTypeReference != null, "primitiveTypeReference != null");

            if (value == null)
            {
                // Only primitive type references are validated. Core model is sufficient.
                ReaderValidationUtils.ValidateNullValue(
                    EdmCoreModel.Instance,
                    primitiveTypeReference,
                    messageReaderSettings,
                    validateNullValue,
                    propertyName);
                return(null);
            }

            value = converter.ConvertFromPayloadValue(value, primitiveTypeReference);

            // otherwise just return the value without doing any conversion
            return(value);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Implementation of the collection reader logic when in state 'Start'.
        /// </summary>
        /// <param name="duplicatePropertyNamesChecker">The duplicate property names checker for the top-level scope.</param>
        /// <returns>true if more items can be read from the reader; otherwise false.</returns>
        /// <remarks>
        /// Pre-Condition:  JsonNodeType.None:      assumes that the JSON reader has not been used yet when not reading a nested payload.
        /// Post-Condition: The reader is positioned on the first node of the first item or the EndArray node of an empty item array
        /// </remarks>
        private bool ReadAtStartImplementationSynchronously(DuplicatePropertyNamesChecker duplicatePropertyNamesChecker)
        {
            Debug.Assert(duplicatePropertyNamesChecker != null, "duplicatePropertyNamesChecker != null");

            IEdmTypeReference actualItemTypeReference;

            this.ExpectedItemTypeReference = ReaderValidationUtils.ValidateCollectionContextUriAndGetPayloadItemTypeReference(
                this.jsonLightCollectionDeserializer.ContextUriParseResult,
                this.ExpectedItemTypeReference);

            // read the start of the collection until we find the content array for top-level collections
            ODataCollectionStart collectionStart = this.jsonLightCollectionDeserializer.ReadCollectionStart(
                duplicatePropertyNamesChecker,
                this.IsReadingNestedPayload,
                this.ExpectedItemTypeReference,
                out actualItemTypeReference);

            if (actualItemTypeReference != null)
            {
                this.ExpectedItemTypeReference = actualItemTypeReference;
            }

            this.jsonLightCollectionDeserializer.JsonReader.ReadStartArray();

            this.EnterScope(ODataCollectionReaderState.CollectionStart, collectionStart);

            return(true);
        }
        /// <summary>
        /// Tries to read a null value from the JSON reader.
        /// </summary>
        /// <param name="jsonReader">The JSON reader to read from.</param>
        /// <param name="inputContext">The input context with all the settings.</param>
        /// <param name="expectedTypeReference">The expected type reference of the value.</param>
        /// <param name="validateNullValue">true to validate null values; otherwise false.</param>
        /// <param name="propertyName">The name of the property whose value is being read, if applicable (used for error reporting).</param>
        /// <param name="isDynamicProperty">Indicates whether the property is dynamic or unknown.</param>
        /// <returns>true if a null value could be read from the JSON reader; otherwise false.</returns>
        /// <remarks>If the method detects a null value it will read it (position the reader after the null value);
        /// otherwise the reader does not move.</remarks>
        internal static bool TryReadNullValue(
            BufferingJsonReader jsonReader,
            ODataInputContext inputContext,
            IEdmTypeReference expectedTypeReference,
            bool validateNullValue,
            string propertyName,
            bool?isDynamicProperty = null)
        {
            Debug.Assert(jsonReader != null, "jsonReader != null");
            Debug.Assert(inputContext != null, "inputContext != null");

            if (jsonReader.NodeType == JsonNodeType.PrimitiveValue && jsonReader.Value == null)
            {
                jsonReader.ReadNext();

                // NOTE: when reading a null value we will never ask the type resolver (if present) to resolve the
                //       type; we always fall back to the expected type.
                ReaderValidationUtils.ValidateNullValue(
                    inputContext.Model,
                    expectedTypeReference,
                    inputContext.MessageReaderSettings,
                    validateNullValue,
                    inputContext.Version,
                    propertyName,
                    isDynamicProperty);

                return(true);
            }

            return(false);
        }
Ejemplo n.º 8
0
        private void ReadPropertiesImplementation(IEdmStructuredType structuredType, List <ODataProperty> properties, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, bool epmPresent)
        {
            if (!base.XmlReader.IsEmptyElement)
            {
                base.XmlReader.ReadStartElement();
                do
                {
                    switch (base.XmlReader.NodeType)
                    {
                    case XmlNodeType.Element:
                        if (base.XmlReader.NamespaceEquals(base.XmlReader.ODataNamespace))
                        {
                            IEdmProperty property       = null;
                            bool         flag           = false;
                            bool         ignoreProperty = false;
                            if (structuredType != null)
                            {
                                property = ReaderValidationUtils.ValidateValuePropertyDefined(base.XmlReader.LocalName, structuredType, base.MessageReaderSettings, out ignoreProperty);
                                if ((property != null) && (property.PropertyKind == EdmPropertyKind.Navigation))
                                {
                                    throw new ODataException(Microsoft.Data.OData.Strings.ODataAtomPropertyAndValueDeserializer_NavigationPropertyInProperties(property.Name, structuredType));
                                }
                                flag = property == null;
                            }
                            if (ignoreProperty)
                            {
                                base.XmlReader.Skip();
                            }
                            else
                            {
                                ODataNullValueBehaviorKind nullValueReadBehaviorKind = (base.ReadingResponse || (property == null)) ? ODataNullValueBehaviorKind.Default : base.Model.NullValueReadBehaviorKind(property);
                                ODataProperty property2 = this.ReadProperty((property == null) ? null : property.Type, nullValueReadBehaviorKind, epmPresent);
                                if (property2 != null)
                                {
                                    if (flag)
                                    {
                                        ValidationUtils.ValidateOpenPropertyValue(property2.Name, property2.Value);
                                    }
                                    duplicatePropertyNamesChecker.CheckForDuplicatePropertyNames(property2);
                                    properties.Add(property2);
                                }
                            }
                        }
                        else
                        {
                            base.XmlReader.Skip();
                        }
                        break;

                    case XmlNodeType.EndElement:
                        break;

                    default:
                        base.XmlReader.Skip();
                        break;
                    }
                }while (base.XmlReader.NodeType != XmlNodeType.EndElement);
            }
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Reads the next <see cref="ODataItem"/> from the message payload.
        /// </summary>
        /// <returns>true if more items were read; otherwise false.</returns>
        private bool ReadImplementation()
        {
            bool result;

            switch (this.State)
            {
            case ODataReaderState.Start:
                result = this.ReadAtStartImplementation();
                break;

            case ODataReaderState.FeedStart:
                result = this.ReadAtFeedStartImplementation();
                break;

            case ODataReaderState.FeedEnd:
                result = this.ReadAtFeedEndImplementation();
                break;

            case ODataReaderState.EntryStart:
                this.IncreaseEntryDepth();
                result = this.ReadAtEntryStartImplementation();
                break;

            case ODataReaderState.EntryEnd:
                this.DecreaseEntryDepth();
                result = this.ReadAtEntryEndImplementation();
                break;

            case ODataReaderState.NavigationLinkStart:
                result = this.ReadAtNavigationLinkStartImplementation();
                break;

            case ODataReaderState.NavigationLinkEnd:
                result = this.ReadAtNavigationLinkEndImplementation();
                break;

            case ODataReaderState.EntityReferenceLink:
                result = this.ReadAtEntityReferenceLink();
                break;

            case ODataReaderState.Exception:        // fall through
            case ODataReaderState.Completed:
                throw new ODataException(Strings.ODataReaderCore_NoReadCallsAllowed(this.State));

            default:
                Debug.Assert(false, "Unsupported reader state " + this.State + " detected.");
                throw new ODataException(Strings.General_InternalError(InternalErrorCodes.ODataReaderCore_ReadImplementation));
            }

            if ((this.State == ODataReaderState.EntryStart || this.State == ODataReaderState.EntryEnd) && this.Item != null)
            {
                ReaderValidationUtils.ValidateEntry(this.CurrentEntry);
            }

            return(result);
        }
Ejemplo n.º 10
0
 private bool TryReadNullValue(IEdmTypeReference expectedTypeReference, bool validateNullValue)
 {
     if ((base.JsonReader.NodeType == JsonNodeType.PrimitiveValue) && (base.JsonReader.Value == null))
     {
         base.JsonReader.ReadNext();
         ReaderValidationUtils.ValidateNullValue(base.Model, expectedTypeReference, base.MessageReaderSettings, validateNullValue, base.Version);
         return(true);
     }
     return(false);
 }
Ejemplo n.º 11
0
 /// <summary>
 /// Validate a null value.
 /// </summary>
 /// <param name="expectedTypeReference">The expected type of the null value.</param>
 /// <param name="validateNullValue">true to validate the null value; false to only check whether the type is
 /// supported.</param>
 /// <param name="propertyName">The name of the property whose value is being read, if applicable
 /// (used for error reporting).</param>
 /// <param name="isDynamicProperty">Indicates whether the property is dynamic or unknown.</param>
 public void ValidateNullValue(IEdmTypeReference expectedTypeReference,
                               bool validateNullValue, string propertyName,
                               bool?isDynamicProperty)
 {
     if (settings.ThrowIfTypeConflictsWithMetadata)
     {
         ReaderValidationUtils.ValidateNullValue(expectedTypeReference, settings.EnablePrimitiveTypeConversion,
                                                 validateNullValue, propertyName, isDynamicProperty);
     }
 }
        private ODataEntityReferenceLink ReadUriElement()
        {
            ODataEntityReferenceLink link = new ODataEntityReferenceLink();
            Uri    xmlBaseUri             = base.XmlReader.XmlBaseUri;
            string uriFromPayload         = base.XmlReader.ReadElementValue();
            Uri    uri2 = base.ProcessUriFromPayload(uriFromPayload, xmlBaseUri);

            link.Url = uri2;
            ReaderValidationUtils.ValidateEntityReferenceLink(link);
            return(link);
        }
Ejemplo n.º 13
0
        /// <summary>
        /// Read a null value from the payload.
        /// </summary>
        /// <param name="expectedTypeReference">The expected type reference (for validation purposes).</param>
        /// <param name="validateNullValue">true to validate the value against the <paramref name="expectedTypeReference"/>.</param>
        /// <returns>The null value.</returns>
        private object ReadNullValue(IEdmTypeReference expectedTypeReference, bool validateNullValue)
        {
            // The m:null attribute has a precedence over the content of the element, thus if we find m:null='true' we ignore the content of the element.
            this.XmlReader.SkipElementContent();

            // NOTE: when reading a null value we will never ask the type resolver (if present) to resolve the
            //       type; we always fall back to the expected type.
            ReaderValidationUtils.ValidateNullValue(this.Model, expectedTypeReference, this.MessageReaderSettings, validateNullValue, this.Version);

            return(null);
        }
Ejemplo n.º 14
0
        /// <summary>
        /// Reads a top-level entity reference link - implementation of the actual functionality.
        /// </summary>
        /// <param name="navigationProperty">The navigation property for which to read the entity reference links.</param>
        /// <param name="duplicatePropertyNamesChecker">The duplicate property names checker to use for the top-level scope.</param>
        /// <returns>An <see cref="ODataEntityReferenceLink"/> representing the read entity reference link.</returns>
        private ODataEntityReferenceLink ReadEntityReferenceLinkImplementation(IEdmNavigationProperty navigationProperty, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker)
        {
            Debug.Assert(duplicatePropertyNamesChecker != null, "duplicatePropertyNamesChecker != null");

            if (this.JsonLightInputContext.ReadingResponse)
            {
                // Validate the metadata URI parsed from the payload against the expected navigation property.
                ReaderValidationUtils.ValidateEntityReferenceLinkMetadataUri(this.MetadataUriParseResult, navigationProperty);
            }

            return(this.ReadSingleEntityReferenceLink(duplicatePropertyNamesChecker, /*topLevel*/ true));
        }
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="rawInputContext">The input context to read the content from.</param>
        /// <param name="encoding">The encoding for the underlying stream.</param>
        internal ODataAsynchronousReader(ODataRawInputContext rawInputContext, Encoding encoding)
        {
            Debug.Assert(rawInputContext != null, "rawInputContext != null");

            // Currently we only support single-byte UTF8 in async reader.
            if (encoding != null)
            {
                ReaderValidationUtils.ValidateEncodingSupportedInAsync(encoding);
            }

            this.rawInputContext = rawInputContext;
        }
Ejemplo n.º 16
0
        private object ReadNonEntityValueImplementation(IEdmTypeReference expectedTypeReference, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, CollectionWithoutExpectedTypeValidator collectionValidator, bool validateNullValue)
        {
            object obj2;
            SerializationTypeNameAnnotation annotation;
            EdmTypeKind  kind;
            JsonNodeType nodeType = base.JsonReader.NodeType;

            if (nodeType == JsonNodeType.StartArray)
            {
                throw new ODataException(Microsoft.Data.OData.Strings.ODataJsonPropertyAndValueDeserializer_CannotReadPropertyValue(nodeType));
            }
            if (this.TryReadNullValue(expectedTypeReference, validateNullValue))
            {
                return(null);
            }
            string            payloadTypeName = this.FindTypeNameInPayload();
            IEdmTypeReference type            = ReaderValidationUtils.ResolvePayloadTypeNameAndComputeTargetType(EdmTypeKind.None, null, expectedTypeReference, payloadTypeName, base.Model, base.MessageReaderSettings, base.Version, new Func <EdmTypeKind>(this.GetNonEntityValueKind), out kind, out annotation);

            switch (kind)
            {
            case EdmTypeKind.Primitive:
            {
                IEdmPrimitiveTypeReference reference2 = (type == null) ? null : type.AsPrimitive();
                if ((payloadTypeName != null) && !reference2.IsSpatial())
                {
                    throw new ODataException(Microsoft.Data.OData.Strings.ODataJsonPropertyAndValueDeserializer_InvalidPrimitiveTypeName(payloadTypeName));
                }
                obj2 = this.ReadPrimitiveValueImplementation(reference2, validateNullValue);
                break;
            }

            case EdmTypeKind.Complex:
                obj2 = this.ReadComplexValueImplementation((type == null) ? null : type.AsComplex(), payloadTypeName, annotation, duplicatePropertyNamesChecker);
                break;

            case EdmTypeKind.Collection:
            {
                IEdmCollectionTypeReference collectionValueTypeReference = ValidationUtils.ValidateCollectionType(type);
                obj2 = this.ReadCollectionValueImplementation(collectionValueTypeReference, payloadTypeName, annotation);
                break;
            }

            default:
                throw new ODataException(Microsoft.Data.OData.Strings.General_InternalError(InternalErrorCodes.ODataJsonPropertyAndValueDeserializer_ReadPropertyValue));
            }
            if (collectionValidator != null)
            {
                string collectionItemTypeName = ODataJsonReaderUtils.GetPayloadTypeName(obj2);
                collectionValidator.ValidateCollectionItem(collectionItemTypeName, kind);
            }
            return(obj2);
        }
Ejemplo n.º 17
0
        /// <summary>
        /// Ensure that a batch encoding exists; if not, detect it from the first couple of bytes of the stream.
        /// </summary>
        /// <param name="stream">The stream to read.</param>
        private void EnsureBatchEncoding(Stream stream)
        {
            // If no batch encoding is specified we detect it from the first bytes in the buffer.
            if (this.batchEncoding == null)
            {
                // NOTE: The batch encoding will only ever be null on the first call to this method which
                //       happens before the batch reader skips to the first boundary.
                this.batchEncoding = this.DetectEncoding(stream);
            }

            // Verify that we only allow single byte encodings and UTF-8 for now.
            ReaderValidationUtils.ValidateEncodingSupportedInBatch(this.batchEncoding);
        }
Ejemplo n.º 18
0
        /// <summary>
        /// Read an entity reference link.
        /// </summary>
        /// <returns>An instance of <see cref="ODataEntityReferenceLink"/> which was read.</returns>
        /// <remarks>
        /// Pre-Condition:  any node   - This method will throw if the node type is not a StartObject node
        /// Post-Condition: any node
        /// </remarks>
        private ODataEntityReferenceLink ReadSingleEntityReferenceLink()
        {
            this.JsonReader.AssertNotBuffering();

            if (this.JsonReader.NodeType != JsonNodeType.StartObject)
            {
                // entity reference link has to be an object
                throw new ODataException(Strings.ODataJsonEntityReferenceLinkDeserializer_EntityReferenceLinkMustBeObjectValue(this.JsonReader.NodeType));
            }

            this.JsonReader.ReadStartObject();

            ODataEntityReferenceLink entityReferenceLink = new ODataEntityReferenceLink();

            while (this.JsonReader.NodeType == JsonNodeType.Property)
            {
                // read the 'uri' property
                string propertyName = this.JsonReader.ReadPropertyName();
                if (string.CompareOrdinal(JsonConstants.ODataUriName, propertyName) == 0)
                {
                    if (entityReferenceLink.Url != null)
                    {
                        throw new ODataException(Strings.ODataJsonEntityReferenceLinkDeserializer_MultipleUriPropertiesInEntityReferenceLink);
                    }

                    // read the value of the 'uri' property
                    string uriString = this.JsonReader.ReadStringValue(JsonConstants.ODataUriName);
                    if (uriString == null)
                    {
                        throw new ODataException(Strings.ODataJsonEntityReferenceLinkDeserializer_EntityReferenceLinkUriCannotBeNull);
                    }

                    entityReferenceLink.Url = this.ProcessUriFromPayload(uriString);
                }
                else
                {
                    // Skip unrecognized properties
                    this.JsonReader.SkipValue();
                }
            }

            ReaderValidationUtils.ValidateEntityReferenceLink(entityReferenceLink);

            // end of the entity reference link object
            this.JsonReader.ReadEndObject();

            this.JsonReader.AssertNotBuffering();
            return(entityReferenceLink);
        }
        /// <summary>
        /// Reads a property.
        /// </summary>
        /// <param name="isTop">whether it is the top level</param>
        /// <param name="expectedPropertyName">The expected property name to be read from the payload (or null if no expected property name was specified).</param>
        /// <param name="expectedPropertyTypeReference">The expected type reference of the property value.</param>
        /// <param name="nullValueReadBehaviorKind">Behavior to use when reading null value for the property.</param>
        /// <returns>The ODataProperty representing the property in question; if null is returned from this method it means that the property is to be ignored.</returns>
        /// <remarks>
        /// Pre-Condition:   XmlNodeType.Element - The XML element representing the property to read.
        ///                                        Note that the method does NOT check for the property name neither it resolves the property against metadata.
        /// Post-Condition:  Any                 - The node after the property.
        /// </remarks>
        private ODataProperty ReadProperty(
            bool isTop,
            string expectedPropertyName,
            IEdmTypeReference expectedPropertyTypeReference,
            ODataNullValueBehaviorKind nullValueReadBehaviorKind)
        {
            Debug.Assert(
                expectedPropertyTypeReference == null || expectedPropertyTypeReference.IsODataPrimitiveTypeKind() || expectedPropertyTypeReference.IsODataEnumTypeKind() ||
                expectedPropertyTypeReference.IsODataComplexTypeKind() || expectedPropertyTypeReference.IsNonEntityCollectionType(),
                "Only primitive, Enum, complex and collection types can be read by this method.");
            this.AssertXmlCondition(XmlNodeType.Element);
            this.XmlReader.AssertNotBuffering();

            ODataProperty property     = new ODataProperty();
            string        propertyName = null;

            if (!isTop)
            {
                propertyName = this.XmlReader.LocalName;
                ValidationUtils.ValidatePropertyName(propertyName);
                ReaderValidationUtils.ValidateExpectedPropertyName(expectedPropertyName, propertyName);
            }

            property.Name = propertyName;

            object propertyValue = this.ReadNonEntityValueImplementation(
                expectedPropertyTypeReference,
                /*duplicatePropertyNamesChecker*/ null,
                /*collectionValidator*/ null,
                nullValueReadBehaviorKind == ODataNullValueBehaviorKind.Default,
                propertyName);

            if (nullValueReadBehaviorKind == ODataNullValueBehaviorKind.IgnoreValue && propertyValue == null)
            {
                property = null;
            }
            else
            {
                property.Value = propertyValue;
            }

            // Read past the end tag of the property or the start tag if the element is empty.
            this.XmlReader.Read();

            this.XmlReader.AssertNotBuffering();
            return(property);
        }
Ejemplo n.º 20
0
        private object ReadNonEntityValueImplementation(IEdmTypeReference expectedTypeReference, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, CollectionWithoutExpectedTypeValidator collectionValidator, bool validateNullValue, bool epmPresent)
        {
            string itemTypeNameFromCollection;
            bool   flag;
            SerializationTypeNameAnnotation annotation;
            EdmTypeKind kind2;

            this.ReadNonEntityValueAttributes(out itemTypeNameFromCollection, out flag);
            if (flag)
            {
                return(this.ReadNullValue(expectedTypeReference, validateNullValue));
            }
            bool flag2 = false;

            if ((collectionValidator != null) && (itemTypeNameFromCollection == null))
            {
                itemTypeNameFromCollection = collectionValidator.ItemTypeNameFromCollection;
                flag2 = collectionValidator.ItemTypeKindFromCollection != EdmTypeKind.None;
            }
            IEdmTypeReference type = ReaderValidationUtils.ResolvePayloadTypeNameAndComputeTargetType(EdmTypeKind.None, edmStringType, expectedTypeReference, itemTypeNameFromCollection, base.Model, base.MessageReaderSettings, base.Version, new Func <EdmTypeKind>(this.GetNonEntityValueKind), out kind2, out annotation);

            if (flag2)
            {
                annotation = new SerializationTypeNameAnnotation {
                    TypeName = null
                };
            }
            if (collectionValidator != null)
            {
                collectionValidator.ValidateCollectionItem(itemTypeNameFromCollection, kind2);
            }
            switch (kind2)
            {
            case EdmTypeKind.Primitive:
                return(this.ReadPrimitiveValue(type.AsPrimitive()));

            case EdmTypeKind.Complex:
                return(this.ReadComplexValue((type == null) ? null : type.AsComplex(), itemTypeNameFromCollection, annotation, duplicatePropertyNamesChecker, epmPresent));

            case EdmTypeKind.Collection:
            {
                IEdmCollectionTypeReference collectionTypeReference = ValidationUtils.ValidateCollectionType(type);
                return(this.ReadCollectionValue(collectionTypeReference, itemTypeNameFromCollection, annotation));
            }
            }
            throw new ODataException(Microsoft.Data.OData.Strings.General_InternalError(InternalErrorCodes.ODataAtomPropertyAndValueDeserializer_ReadNonEntityValue));
        }
Ejemplo n.º 21
0
 /// <summary>
 /// Resolves and validates the payload type against the expected type and returns the target type.
 /// </summary>
 /// <param name="expectedTypeKind">The expected type kind for the value.</param>
 /// <param name="expectStructuredType">This value indicates if a structured type is expected to be return.
 /// True for structured type, false for non-structured type, null for indetermination.</param>
 /// <param name="defaultPrimitivePayloadType">The default payload type if none is specified in the payload;
 /// for ATOM this is Edm.String, for JSON it is null since there is no payload type name for primitive types in the payload.</param>
 /// <param name="expectedTypeReference">The expected type reference, or null if no expected type is available.</param>
 /// <param name="payloadTypeName">The payload type name, or null if no payload type was specified.</param>
 /// <param name="model">The model to use.</param>
 /// <param name="typeKindFromPayloadFunc">A func to compute the type kind from the payload shape if it could not be determined from the expected type or the payload type.</param>
 /// <param name="targetTypeKind">The target type kind to be used to read the payload.</param>
 /// <param name="typeAnnotation">Potentially non-null instance of an annotation to put on the value reported from the reader.</param>
 /// <returns>
 /// The target type reference to use for parsing the value.
 /// If there is no user specified model, this will return null.
 /// If there is a user specified model, this method never returns null.
 /// </returns>
 /// <remarks>
 /// This method cannot be used for primitive type resolution. Primitive type resolution is format dependent and format specific methods should be used instead.
 /// </remarks>
 public IEdmTypeReference ResolvePayloadTypeNameAndComputeTargetType(
     EdmTypeKind expectedTypeKind,
     bool?expectStructuredType,
     IEdmType defaultPrimitivePayloadType,
     IEdmTypeReference expectedTypeReference,
     string payloadTypeName,
     IEdmModel model,
     Func <EdmTypeKind> typeKindFromPayloadFunc,
     out EdmTypeKind targetTypeKind,
     out ODataTypeAnnotation typeAnnotation)
 {
     return(ReaderValidationUtils.ResolvePayloadTypeNameAndComputeTargetType(
                expectedTypeKind, expectStructuredType, defaultPrimitivePayloadType, expectedTypeReference, payloadTypeName, model,
                settings.ClientCustomTypeResolver, settings.ThrowIfTypeConflictsWithMetadata,
                settings.EnablePrimitiveTypeConversion,
                typeKindFromPayloadFunc, out targetTypeKind, out typeAnnotation));
 }
        /// <summary>
        /// Reads a property.
        /// </summary>
        /// <param name="expectedPropertyName">The expected property name to be read from the payload (or null if no expected property name was specified).</param>
        /// <param name="expectedPropertyTypeReference">The expected type reference of the property value.</param>
        /// <param name="nullValueReadBehaviorKind">Behavior to use when reading null value for the property.</param>
        /// <param name="epmPresent">Whether any EPM mappings exist.</param>
        /// <returns>The ODataProperty representing the property in question; if null is returned from this method it means that the property is to be ignored.</returns>
        /// <remarks>
        /// Pre-Condition:   XmlNodeType.Element - The XML element representing the property to read.
        ///                                        Note that the method does NOT check for the property name neither it resolves the property against metadata.
        /// Post-Condition:  Any                 - The node after the property.
        /// </remarks>
        private ODataProperty ReadProperty(
            string expectedPropertyName,
            IEdmTypeReference expectedPropertyTypeReference,
            ODataNullValueBehaviorKind nullValueReadBehaviorKind,
            bool epmPresent)
        {
            Debug.Assert(
                expectedPropertyTypeReference == null || expectedPropertyTypeReference.IsODataPrimitiveTypeKind() ||
                expectedPropertyTypeReference.IsODataComplexTypeKind() || expectedPropertyTypeReference.IsNonEntityCollectionType(),
                "Only primitive, complex and collection types can be read by this method.");
            this.AssertXmlCondition(XmlNodeType.Element);
            Debug.Assert(this.UseServerFormatBehavior || this.XmlReader.NamespaceEquals(this.XmlReader.ODataNamespace), "Property elements must be in the OData namespace (unless we are running in WCF DS server format mode).");
            this.XmlReader.AssertNotBuffering();

            ODataProperty property     = new ODataProperty();
            string        propertyName = this.XmlReader.LocalName;

            ValidationUtils.ValidatePropertyName(propertyName);
            ReaderValidationUtils.ValidateExpectedPropertyName(expectedPropertyName, propertyName);
            property.Name = propertyName;

            object propertyValue = this.ReadNonEntityValueImplementation(
                expectedPropertyTypeReference,
                /*duplicatePropertyNamesChecker*/ null,
                /*collectionValidator*/ null,
                nullValueReadBehaviorKind == ODataNullValueBehaviorKind.Default,
                epmPresent,
                propertyName);

            if (nullValueReadBehaviorKind == ODataNullValueBehaviorKind.IgnoreValue && propertyValue == null)
            {
                property = null;
            }
            else
            {
                property.Value = propertyValue;
            }

            // Read past the end tag of the property or the start tag if the element is empty.
            this.XmlReader.Read();

            this.XmlReader.AssertNotBuffering();
            return(property);
        }
Ejemplo n.º 23
0
 private void ReadPropertiesMetadataProperty(IODataJsonReaderEntryState entryState, ref ODataJsonReaderUtils.MetadataPropertyBitMask metadataPropertiesFoundBitField)
 {
     if (!base.ReadingResponse || (base.MessageReaderSettings.MaxProtocolVersion < ODataVersion.V3))
     {
         base.JsonReader.SkipValue();
     }
     else
     {
         ODataJsonReaderUtils.VerifyMetadataPropertyNotFound(ref metadataPropertiesFoundBitField, ODataJsonReaderUtils.MetadataPropertyBitMask.Properties, "properties");
         if (base.JsonReader.NodeType != JsonNodeType.StartObject)
         {
             throw new ODataException(Microsoft.Data.OData.Strings.ODataJsonEntryAndFeedDeserializer_PropertyInEntryMustHaveObjectValue("properties", base.JsonReader.NodeType));
         }
         base.JsonReader.ReadStartObject();
         while (base.JsonReader.NodeType == JsonNodeType.Property)
         {
             string associationLinkName = base.JsonReader.ReadPropertyName();
             ValidationUtils.ValidateAssociationLinkName(associationLinkName);
             ReaderValidationUtils.ValidateNavigationPropertyDefined(associationLinkName, entryState.EntityType, base.MessageReaderSettings);
             base.JsonReader.ReadStartObject();
             while (base.JsonReader.NodeType == JsonNodeType.Property)
             {
                 if (string.CompareOrdinal(base.JsonReader.ReadPropertyName(), "associationuri") == 0)
                 {
                     string propertyValue = base.JsonReader.ReadStringValue("associationuri");
                     ODataJsonReaderUtils.ValidateMetadataStringProperty(propertyValue, "associationuri");
                     ODataAssociationLink associationLink = new ODataAssociationLink {
                         Name = associationLinkName,
                         Url  = base.ProcessUriFromPayload(propertyValue)
                     };
                     ValidationUtils.ValidateAssociationLink(associationLink);
                     entryState.DuplicatePropertyNamesChecker.CheckForDuplicatePropertyNames(associationLink);
                     ReaderUtils.AddAssociationLinkToEntry(entryState.Entry, associationLink);
                 }
                 else
                 {
                     base.JsonReader.SkipValue();
                 }
             }
             base.JsonReader.ReadEndObject();
         }
         base.JsonReader.ReadEndObject();
     }
 }
        /// <summary>
        /// If an entity type name is found in the payload this method is called to apply it to the current scope.
        /// This method should be called even if the type name was not found in which case a null should be passed in.
        /// The method validates that some type will be available as the current entity type after it returns (if we are parsing using metadata).
        /// </summary>
        /// <param name="entityTypeNameFromPayload">The entity type name found in the payload or null if no type was specified in the payload.</param>
        protected void ApplyEntityTypeNameFromPayload(string entityTypeNameFromPayload)
        {
            Debug.Assert(
                this.scopes.Count > 0 && this.scopes.Peek().Item is ODataEntry,
                "Entity type can be applied only when in entry scope.");

            SerializationTypeNameAnnotation serializationTypeNameAnnotation;
            EdmTypeKind             targetTypeKind;
            IEdmEntityTypeReference targetEntityTypeReference =
                (IEdmEntityTypeReference)ReaderValidationUtils.ResolvePayloadTypeNameAndComputeTargetType(
                    EdmTypeKind.Entity,
                    /*defaultPrimitivePayloadType*/ null,
                    this.CurrentEntityType.ToTypeReference(),
                    entityTypeNameFromPayload,
                    this.inputContext.Model,
                    this.inputContext.MessageReaderSettings,
                    this.inputContext.Version,
                    () => EdmTypeKind.Entity,
                    out targetTypeKind,
                    out serializationTypeNameAnnotation);

            IEdmEntityType targetEntityType = null;
            ODataEntry     entry            = this.CurrentEntry;

            if (targetEntityTypeReference != null)
            {
                targetEntityType = targetEntityTypeReference.EntityDefinition();
                entry.TypeName   = targetEntityType.ODataFullName();

                if (serializationTypeNameAnnotation != null)
                {
                    entry.SetAnnotation(serializationTypeNameAnnotation);
                }
            }
            else if (entityTypeNameFromPayload != null)
            {
                entry.TypeName = entityTypeNameFromPayload;
            }

            // Set the current entity type since the type from payload might be more derived than
            // the expected one.
            this.CurrentEntityType = targetEntityType;
        }
        /// <summary>
        /// Read an entity reference link.
        /// </summary>
        /// <returns>An instance of <see cref="ODataEntityReferenceLink"/> which was read.</returns>
        /// <remarks>
        /// Pre-Condition:  XmlNodeType.Element - the 'm:ref' element to read.
        /// Post-Condition: Any                 - the node after the 'm:ref' element which was read.
        /// </remarks>
        private ODataEntityReferenceLink ReadEntityReferenceId()
        {
            Debug.Assert(this.XmlReader != null, "this.XmlReader != null");
            this.AssertXmlCondition(XmlNodeType.Element);
            Debug.Assert(this.XmlReader.NamespaceURI == this.XmlReader.ODataMetadataNamespace, "this.XmlReader.NamespaceURI == this.XmlReader.ODataMetadataNamespace");
            Debug.Assert(this.XmlReader.LocalName == this.ODataRefElementName, "this.XmlReader.LocalName == this.ODataRefElementName");

            ODataEntityReferenceLink link = new ODataEntityReferenceLink();

            string uriString = this.XmlReader.GetAttribute(AtomConstants.AtomIdElementName);

            Debug.Assert(uriString != null, "In ATOM a entity reference id attribute on ref element can never represent a null value.");
            Uri xmlBaseUri = this.XmlReader.XmlBaseUri;
            Uri uri        = this.ProcessUriFromPayload(uriString, xmlBaseUri);

            link.Url = uri;

            this.XmlReader.Skip();
            ReaderValidationUtils.ValidateEntityReferenceLink(link);
            return(link);
        }
Ejemplo n.º 26
0
        /// <summary>
        /// Reads the headers of a part.
        /// </summary>
        /// <param name="contentId">Content-ID read from changeset header, null if changeset part detected</param>
        /// <returns>true if the start of a changeset part was detected; otherwise false.</returns>
        internal bool ProcessPartHeader(out string contentId)
        {
            Debug.Assert(this.batchEncoding != null, "Batch encoding should have been established on first call to SkipToBoundary.");

            bool isChangeSetPart;
            ODataBatchOperationHeaders headers = this.ReadPartHeaders(out isChangeSetPart);

            contentId = null;

            if (isChangeSetPart)
            {
                // determine the changeset boundary and the changeset encoding from the content type header
                this.DetermineChangesetBoundaryAndEncoding(headers[ODataConstants.ContentTypeHeader]);

                if (this.changesetEncoding == null)
                {
                    // NOTE: No changeset encoding was specified in the changeset's content type header.
                    //       Determine the changeset encoding from the first bytes in the changeset.
                    // NOTE: We do not have to skip over the potential preamble of the encoding
                    //       because the batch reader will skip over everything (incl. the preamble)
                    //       until it finds the first changeset (or batch) boundary
                    this.changesetEncoding = this.DetectEncoding(this.multipartMixedBatchInputContext.Stream);
                }

                // Verify that we only allow single byte encodings and UTF-8 for now.
                ReaderValidationUtils.ValidateEncodingSupportedInBatch(this.changesetEncoding);
            }
            else
            {
                // Read the contentId not only for request in changeset; but also
                // top-level request (if available), so that top-level request dependsOn
                // ids can be derived (even though top-level request ids are typically
                // not showing up on the wire).
                headers.TryGetValue(ODataConstants.ContentIdHeader, out contentId);
            }

            return(isChangeSetPart);
        }
        /// <summary>
        /// Reads an annotation's value from the annotation value notation specified on the current element.
        /// </summary>
        /// <param name="expectedTypeReference">The expected type reference of the vocabulary term from the metadata.</param>
        /// <param name="attributeValueNotationTypeReference">The type reference indicated by the name of the attribute used in attribute value notation.
        ///   For example, if the attribute was called "string", this will be a reference to the string type.</param>
        /// <param name="attributeValueNotationAttributeName">The name of the attribute used by attribute avalue notation.</param>
        /// <param name="attributeValueNotationAttributeValue">The value of the attribute used by attribute value notation.</param>
        /// <param name="typeAttributeValue">The value of the "m:type" attribute on the annotation element.</param>
        /// <param name="positionedOnEmptyElement">true if the annotation element is empty, false otherwise.</param>
        /// <param name="model">The edm model instance.</param>
        /// <param name="messageReaderSettings">The message reader settings instance.</param>
        /// <param name="version">The payload version to read.</param>
        /// <returns>The primitive value represented on this element via attribute value notation.</returns>
        private static ODataPrimitiveValue GetValueFromAttributeValueNotation(
            IEdmTypeReference expectedTypeReference,
            IEdmPrimitiveTypeReference attributeValueNotationTypeReference,
            string attributeValueNotationAttributeName,
            string attributeValueNotationAttributeValue,
            string typeAttributeValue,
            bool positionedOnEmptyElement,
            IEdmModel model,
            ODataMessageReaderSettings messageReaderSettings,
            ODataVersion version)
        {
            Debug.Assert(attributeValueNotationTypeReference != null, "attributeValueNotationTypeReference != null");

            if (!positionedOnEmptyElement)
            {
                // If there is content in the body of the element, throw since it's ambiguous whether we should use the value from the attribute or the element content.
                throw new ODataException(ODataErrorStrings.AtomInstanceAnnotation_AttributeValueNotationUsedOnNonEmptyElement(attributeValueNotationAttributeName));
            }

            // If both m:type is present and attribute value notation is being used, they must match.
            // For example, if m:type is "Edm.Int32", but the "string" attribute is also present, we should throw.
            if (typeAttributeValue != null && !string.Equals(attributeValueNotationTypeReference.Definition.ODataFullName(), typeAttributeValue, StringComparison.Ordinal))
            {
                throw new ODataException(ODataErrorStrings.AtomInstanceAnnotation_AttributeValueNotationUsedWithIncompatibleType(typeAttributeValue, attributeValueNotationAttributeName));
            }

            IEdmTypeReference targetTypeReference = ReaderValidationUtils.ResolveAndValidatePrimitiveTargetType(
                expectedTypeReference,
                EdmTypeKind.Primitive,
                attributeValueNotationTypeReference.Definition,
                attributeValueNotationTypeReference.ODataFullName(),
                attributeValueNotationTypeReference.Definition,
                model,
                messageReaderSettings,
                version);

            return(new ODataPrimitiveValue(AtomValueUtils.ConvertStringToPrimitive(attributeValueNotationAttributeValue, targetTypeReference.AsPrimitive())));
        }
Ejemplo n.º 28
0
        /// <summary>
        /// Read a set of top-level entity reference links.
        /// </summary>
        /// <param name="navigationProperty">The navigation property for which to read the entity reference links.</param>
        /// <param name="duplicatePropertyNamesChecker">The duplicate property names checker to use for the top-level scope.</param>
        /// <returns>An <see cref="ODataEntityReferenceLinks"/> representing the read links.</returns>
        private ODataEntityReferenceLinks ReadEntityReferenceLinksImplementation(IEdmNavigationProperty navigationProperty, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker)
        {
            Debug.Assert(duplicatePropertyNamesChecker != null, "duplicatePropertyNamesChecker != null");

            ODataEntityReferenceLinks entityReferenceLinks = new ODataEntityReferenceLinks();

            if (this.JsonLightInputContext.ReadingResponse)
            {
                // Validate the metadata URI parsed from the payload against the expected navigation property.
                ReaderValidationUtils.ValidateEntityReferenceLinkMetadataUri(this.MetadataUriParseResult, navigationProperty);
            }

            this.ReadEntityReferenceLinksAnnotations(entityReferenceLinks, duplicatePropertyNamesChecker, /*forLinksStart*/ true);

            // Read the start of the content array of the links
            this.JsonReader.ReadStartArray();

            List <ODataEntityReferenceLink> links = new List <ODataEntityReferenceLink>();
            DuplicatePropertyNamesChecker   linkDuplicatePropertyNamesChecker = this.JsonLightInputContext.CreateDuplicatePropertyNamesChecker();

            while (this.JsonReader.NodeType != JsonNodeType.EndArray)
            {
                // read another link
                ODataEntityReferenceLink entityReferenceLink = this.ReadSingleEntityReferenceLink(linkDuplicatePropertyNamesChecker, /*topLevel*/ false);
                links.Add(entityReferenceLink);
                linkDuplicatePropertyNamesChecker.Clear();
            }

            this.JsonReader.ReadEndArray();

            this.ReadEntityReferenceLinksAnnotations(entityReferenceLinks, duplicatePropertyNamesChecker, /*forLinksStart*/ false);

            this.JsonReader.ReadEndObject();

            entityReferenceLinks.Links = new ReadOnlyEnumerable <ODataEntityReferenceLink>(links);
            return(entityReferenceLinks);
        }
Ejemplo n.º 29
0
        /// <summary>
        /// Read an entity reference link.
        /// </summary>
        /// <returns>An instance of <see cref="ODataEntityReferenceLink"/> which was read.</returns>
        /// <remarks>
        /// Pre-Condition:  XmlNodeType.Element - the 'd:uri' element to read.
        /// Post-Condition: Any                 - the node after the 'd:uri' element which was read.
        /// </remarks>
        private ODataEntityReferenceLink ReadUriElement()
        {
            Debug.Assert(this.XmlReader != null, "this.XmlReader != null");
            this.AssertXmlCondition(XmlNodeType.Element);
            Debug.Assert(
                this.XmlReader.NamespaceURI == this.XmlReader.ODataNamespace || this.XmlReader.NamespaceURI == this.XmlReader.ODataMetadataNamespace,
                "this.XmlReader.NamespaceURI == this.XmlReader.ODataNamespace  || this.XmlReader.NamespaceURI == this.XmlReader.ODataMetadataNamespace");
            Debug.Assert(this.XmlReader.LocalName == this.ODataUriElementName, "this.XmlReader.LocalName == this.ODataUriElementName");

            ODataEntityReferenceLink link = new ODataEntityReferenceLink();

            // NOTE: get the base URI here before we read the content as string; reading the content as string will move the
            //       reader to the end element and thus we lose the xml:base definition on the element.
            Uri    xmlBaseUri = this.XmlReader.XmlBaseUri;
            string uriString  = this.XmlReader.ReadElementValue();

            Debug.Assert(uriString != null, "In ATOM a URI element can never represent a null value.");
            Uri uri = this.ProcessUriFromPayload(uriString, xmlBaseUri);

            link.Url = uri;

            ReaderValidationUtils.ValidateEntityReferenceLink(link);
            return(link);
        }
Ejemplo n.º 30
0
        /// <summary>
        /// Reads the content of a properties in an element (complex value, m:properties, ...)
        /// </summary>
        /// <param name="structuredType">The type which should declare the properties to be read. Optional.</param>
        /// <param name="properties">The list of properties to add properties to.</param>
        /// <param name="duplicatePropertyNamesChecker">The duplicate property names checker to use.</param>
        /// <param name="epmPresent">Whether any EPM mappings exist.</param>
        /// <remarks>
        /// Pre-Condition:  XmlNodeType.Element    - The element to read properties from.
        /// Post-Condition: XmlNodeType.Element    - The element to read properties from if it is an empty element.
        ///                 XmlNodeType.EndElement - The end element of the element to read properties from.
        /// </remarks>
        private void ReadPropertiesImplementation(IEdmStructuredType structuredType, List <ODataProperty> properties, DuplicatePropertyNamesChecker duplicatePropertyNamesChecker, bool epmPresent)
        {
            Debug.Assert(properties != null, "properties != null");
            Debug.Assert(duplicatePropertyNamesChecker != null, "duplicatePropertyNamesChecker != null");
            this.AssertXmlCondition(XmlNodeType.Element);

            // Empty values are valid - they have no properties
            if (!this.XmlReader.IsEmptyElement)
            {
                // Read over the complex value element to its first child node (or end-element)
                this.XmlReader.ReadStartElement();

                do
                {
                    switch (this.XmlReader.NodeType)
                    {
                    case XmlNodeType.Element:
                        if (this.XmlReader.NamespaceEquals(this.XmlReader.ODataNamespace))
                        {
                            // Found a property
                            IEdmProperty edmProperty    = null;
                            bool         isOpen         = false;
                            bool         ignoreProperty = false;

                            if (structuredType != null)
                            {
                                // Lookup the property in metadata
                                edmProperty = ReaderValidationUtils.ValidateValuePropertyDefined(this.XmlReader.LocalName, structuredType, this.MessageReaderSettings, out ignoreProperty);
                                if (edmProperty != null && edmProperty.PropertyKind == EdmPropertyKind.Navigation)
                                {
                                    throw new ODataException(o.Strings.ODataAtomPropertyAndValueDeserializer_NavigationPropertyInProperties(edmProperty.Name, structuredType));
                                }

                                // If the property was not declared, it must be open.
                                isOpen = edmProperty == null;
                            }

                            if (ignoreProperty)
                            {
                                this.XmlReader.Skip();
                            }
                            else
                            {
                                ODataNullValueBehaviorKind nullValueReadBehaviorKind = this.ReadingResponse || edmProperty == null
                                        ? ODataNullValueBehaviorKind.Default
                                        : this.Model.NullValueReadBehaviorKind(edmProperty);
                                ODataProperty property = this.ReadProperty(edmProperty == null ? null : edmProperty.Type, nullValueReadBehaviorKind, epmPresent);
                                Debug.Assert(
                                    property != null || nullValueReadBehaviorKind == ODataNullValueBehaviorKind.IgnoreValue,
                                    "If we don't ignore null values the property must not be null.");

                                if (property != null)
                                {
                                    if (isOpen)
                                    {
                                        ValidationUtils.ValidateOpenPropertyValue(property.Name, property.Value);
                                    }

                                    duplicatePropertyNamesChecker.CheckForDuplicatePropertyNames(property);
                                    properties.Add(property);
                                }
                            }
                        }
                        else
                        {
                            this.XmlReader.Skip();
                        }

                        break;

                    case XmlNodeType.EndElement:
                        // End of the complex value.
                        break;

                    default:
                        // Non-element so for example a text node, just ignore
                        this.XmlReader.Skip();
                        break;
                    }
                }while (this.XmlReader.NodeType != XmlNodeType.EndElement);
            }
        }