/// <summary>
            /// Visits a payload element whose root is a NullPropertyInstance.
            /// </summary>
            /// <param name="payloadElement">The root node of payload element being visited.</param>
            public void Visit(NullPropertyInstance payloadElement)
            {
                ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");
                bool needsWrapping = this.isRootElement;
                this.isRootElement = false;
                if (needsWrapping)
                {
                    this.writer.StartObjectScope();
                }

                if (!string.IsNullOrEmpty(payloadElement.Name))
                {
                    this.writer.WriteName(payloadElement.Name);
                }
                
                this.writer.WriteNull();

                if (needsWrapping)
                {
                    this.writer.EndScope();
                }
            }
            /// <summary>
            /// Because the test deserializer used to parse the actual payload will not have metadata, we fix it up here.
            /// Note: this should probably move to happen just before comparison, rather than when generating expectations.
            /// </summary>
            /// <param name="payloadElement">The payload element</param>
            private void SortAndNormalizeProperties(ComplexInstance payloadElement)
            {
                var sortedProperties = payloadElement.Properties.OrderBy(p => p.Name).ToList();
                foreach (var p in sortedProperties)
                {
                    var property = p;
                    payloadElement.Remove(property);

                    // If we have a primitive property with null value, we write a type name for the null value
                    // in V1 and V2. If not type name is available or we are in V3, we don't do that and thus expect a null property instance.
                    var primitiveProperty = property as PrimitiveProperty;
                    if (primitiveProperty != null && primitiveProperty.Value.IsNull && 
                        (this.dsv >= DataServiceProtocolVersion.V4 || string.IsNullOrEmpty(primitiveProperty.Value.FullTypeName)))
                    {
                        property = new NullPropertyInstance(property.Name, null).WithAnnotations(property.Annotations);
                    }

                    var complexProperty = property as ComplexProperty;
                    if (complexProperty != null && complexProperty.Value.IsNull)
                    {
                        property = new NullPropertyInstance(property.Name, complexProperty.Value.FullTypeName).WithAnnotations(property.Annotations);
                    }

                    var complexCollectionProperty = property as ComplexMultiValueProperty;
                    if (complexCollectionProperty != null && complexCollectionProperty.Value.Count == 0 && complexCollectionProperty.Value.FullTypeName == null)
                    {
                        property = new PrimitiveProperty(complexCollectionProperty.Name, complexCollectionProperty.Value.FullTypeName, string.Empty);
                    }

                    payloadElement.Add(property);
                }
            }
        /// <summary>
        /// Replaces the null property instance with a more specific type
        /// </summary>
        /// <param name="payloadElement">The payload element to potentially replace</param>
        /// <returns>The original element or a copy to replace it with</returns>
        public override ODataPayloadElement Visit(NullPropertyInstance payloadElement)
        {
            ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");

            var memberPropertyAnnotation = payloadElement.Annotations.OfType<MemberPropertyAnnotation>().SingleOrDefault();
            if (memberPropertyAnnotation != null)
            {
                var memberProperty = memberPropertyAnnotation.Property;
                ExceptionUtilities.CheckObjectNotNull(memberProperty, "Member property annotation was null");

                var primitiveType = memberProperty.PropertyType as PrimitiveDataType;
                if (primitiveType != null)
                {
                    return payloadElement.ReplaceWith(new PrimitiveProperty(payloadElement.Name, payloadElement.FullTypeName, null));
                }

                var complexType = memberProperty.PropertyType as ComplexDataType;
                if (complexType != null)
                {
                    return payloadElement.ReplaceWith(new ComplexProperty(payloadElement.Name, new ComplexInstance(payloadElement.FullTypeName, true)));
                }

                var collectionType = memberProperty.PropertyType as CollectionDataType;
                ExceptionUtilities.CheckObjectNotNull(collectionType, "Property type was not primitive, complex, or collection");

                primitiveType = collectionType.ElementDataType as PrimitiveDataType;
                if (primitiveType != null)
                {
                    return payloadElement.ReplaceWith(new PrimitiveMultiValueProperty(payloadElement.Name, new PrimitiveMultiValue(payloadElement.FullTypeName, true)));
                }

                complexType = collectionType.ElementDataType as ComplexDataType;
                ExceptionUtilities.CheckObjectNotNull(complexType, "Collection element type was not primitive or complex");
                return payloadElement.ReplaceWith(new ComplexMultiValueProperty(payloadElement.Name, new ComplexMultiValue(payloadElement.FullTypeName, true)));
            }

            var navigationPropertyAnnotation = payloadElement.Annotations.OfType<NavigationPropertyAnnotation>().SingleOrDefault();
            if (navigationPropertyAnnotation == null)
            {
                return payloadElement;
            }

            return payloadElement.ReplaceWith(new NavigationPropertyInstance(payloadElement.Name, new ExpandedLink()));
        }
 /// <summary>
 /// Visits a null property instance and adds a property with a name and null value
 /// </summary>
 /// <param name="payloadElement">Null property to add to writter list</param>
 public override void Visit(NullPropertyInstance payloadElement)
 {
     this.odataProperties.Add(CreateProperty(payloadElement.Name, null));
 }
        /// <summary>
        /// Throws an InvalidOperationExcption; we expect null properties to be removed by the normalizer.
        /// </summary>
        /// <param name="payloadElement">The null property to process.</param>
        public override void Visit(NullPropertyInstance payloadElement)
        {
            ODataProperty property = new ODataProperty
            {
                Name=payloadElement.Name,
                Value=null
            };

            this.currentProperties.Add(property );
        }
        /// <summary>
        /// Deserializes the element as either a complex, a primitive, or a null property, based on the content
        /// </summary>
        /// <param name="property">The xml to deserialize</param>
        /// <param name="typeNameFallback">TypeName to use instead of the one from the XElement[type] attribute</param>
        /// <returns>A property representing the given xml</returns>
        private PropertyInstance DeserializeProperty(XElement property, string typeNameFallback)
        {
            string propertyName = property.Name.LocalName;

            // get the type name
            string typeNameFromPayload = null;
            XAttribute typeAttribute = property.Attribute(MetadataType);
            if (typeAttribute != null)
            {
                typeNameFromPayload = typeAttribute.Value;
            }

            // set type to be fallback when typeattribute does not exist
            var typeNameForClrTypeLookup = typeNameFromPayload;
            if (typeNameForClrTypeLookup == null && !string.IsNullOrEmpty(typeNameFallback))
            {
                typeNameForClrTypeLookup = typeNameFallback;
            }

            // try to infer the clr type
            Type clrType = null;
            if (!string.IsNullOrEmpty(typeNameForClrTypeLookup))
            {
                ExceptionUtilities.CheckObjectNotNull(this.PrimitiveDataTypeConverter, "Cannot infer clr type from edm type without converter");
                clrType = this.PrimitiveDataTypeConverter.ToClrType(typeNameForClrTypeLookup);
            }

            PropertyInstance result;
            if (property.HasElements)
            {
                // must be complex, a multivalue, or spatial
                ExceptionUtilities.CheckObjectNotNull(this.SpatialFormatter, "Cannot safely deserialize element with children without spatial formatter.");

                // try to infer which spatial type hierarchy it is from the type name in the payload
                SpatialTypeKind? kind = null;
                if (clrType != null)
                {
                    SpatialUtilities.TryInferSpatialTypeKind(clrType, out kind);
                }

                object spatialInstance;
                if (this.SpatialFormatter.TryParse(property.Elements().First(), kind, out spatialInstance))
                {
                    ExceptionUtilities.Assert(property.Elements().Count() == 1, "Spatial property had more than 1 sub-element");
                    result = new PrimitiveProperty(propertyName, typeNameFromPayload, spatialInstance);
                }
                else if (property.Elements().All(e => e.Name == DataServicesElement))
                {
                    result = this.DeserializeCollectionProperty(property);
                }
                else
                {
                    result = new ComplexProperty(propertyName, this.DeserializeComplexInstance(property));
                }
            }
            else
            {
                // check for the null attribute
                bool isNull = false;
                XAttribute isNullAttribute = property.Attribute(MetadataNull);
                if (isNullAttribute != null)
                {
                    isNull = bool.Parse(isNullAttribute.Value);
                }

                // If its null and we can't tell whether it is primitive or complex, then return a null marker
                if (isNull && clrType == null)
                {
                    result = new NullPropertyInstance(propertyName, typeNameFromPayload);
                }
                else if (typeNameFromPayload != null && typeNameFromPayload.StartsWith(ODataConstants.BeginMultiValueTypeIdentifier, StringComparison.Ordinal))
                {
                    ExceptionUtilities.CheckObjectNotNull(this.PrimitiveDataTypeConverter, "Cannot infer clr type from edm type without converter");

                    string elementTypeName = ParseBagElementTypeName(typeNameFromPayload);
                    if (this.PrimitiveDataTypeConverter.ToClrType(elementTypeName) != null)
                    {
                        result = new PrimitiveMultiValueProperty(propertyName, new PrimitiveMultiValue(typeNameFromPayload, isNull));
                    }
                    else
                    {
                        result = new ComplexMultiValueProperty(propertyName, new ComplexMultiValue(typeNameFromPayload, isNull));
                    }
                }
                else
                {
                    object value;
                    if (isNull)
                    {
                        value = null;
                    }
                    else if (clrType != null)
                    {
                        ExceptionUtilities.CheckObjectNotNull(this.PrimitiveConverter, "PrimitiveConverter has not been set.");
                        value = this.PrimitiveConverter.DeserializePrimitive(property.Value, clrType);
                    }
                    else
                    {
                        value = property.Value;
                    }

                    result = new PrimitiveProperty(propertyName, typeNameFromPayload, value);
                }
            }

            AddXmlBaseAnnotation(result, property);

            return result;
        }
        /// <summary>
        /// Throws an InvalidOperationExcption; we expect null properties to be removed by the normalizer.
        /// </summary>
        /// <param name="payloadElement">The null property to process.</param>
        public override void Visit(NullPropertyInstance payloadElement)
        {
            var parent = this.items.Peek();
            ODataProperty property = new ODataProperty
            {
                Name = payloadElement.Name,
                Value = null
            };

            if (parent == null)
            {
                this.items.Push(property);
            }
            else
            { 
                var entry = parent as ODataEntry;
                if (entry != null)
                {
                    var properties = (List<ODataProperty>)entry.Properties;
                    properties.Add(property);
                }

                var complex = parent as ODataComplexValue;
                if (complex != null)
                {
                    var properties = (List<ODataProperty>)complex.Properties;
                    properties.Add(property);
                }
            }
        }
            /// <summary>
            /// Visits a payload element whose root is a NullPropertyInstance.
            /// </summary>
            /// <param name="payloadElement">The root node of payload element being visited.</param>
            public void Visit(NullPropertyInstance payloadElement)
            {
                ExceptionUtilities.CheckArgumentNotNull(payloadElement, "payloadElement");

                var current = this.expectedValueStack.Peek();
                ExceptionUtilities.CheckObjectNotNull(current, "Value was unexpectedly null");
                this.parent.Assert.IsTrue(current.IsNull, string.Format(CultureInfo.InvariantCulture, "Property '{0}' was unexpectedly non-null", payloadElement.Name));
                this.VerifyTypeName(current, payloadElement.FullTypeName, "Type name did not match expectation for null property");
            }
 /// <summary>
 /// Visits the payload element and throws not supported
 /// </summary>
 /// <param name="payloadElement">The payload element to visit</param>
 public override void Visit(NullPropertyInstance payloadElement)
 {
     throw new TaupoNotSupportedException("Should have been fixed in normalizer");
 }
 /// <summary>
 /// Normalizes a null property.
 /// </summary>
 /// <param name="payloadElement">The payload element to normalize.</param>
 public override void Visit(NullPropertyInstance payloadElement)
 {
     base.Visit(payloadElement);
     this.NormalizePropertyName(payloadElement);
 }