internal static void AddTypeNameAnnotationAsNeeded(ODataComplexValue value, ODataMetadataLevel metadataLevel)
        {
            // ODataLib normally has the caller decide whether or not to serialize properties by leaving properties
            // null when values should not be serialized. The TypeName property is different and should always be
            // provided to ODataLib to enable model validation. A separate annotation is used to decide whether or not
            // to serialize the type name (a null value prevents serialization).

            Contract.Assert(value != null);

            // Only add an annotation if we want to override ODataLib's default type name serialization behavior.
            if (ShouldAddTypeNameAnnotation(metadataLevel))
            {
                string typeName;

                // Provide the type name to serialize (or null to force it not to serialize).
                if (ShouldSuppressTypeNameSerialization(metadataLevel))
                {
                    typeName = null;
                }
                else
                {
                    typeName = value.TypeName;
                }

                value.SetAnnotation<SerializationTypeNameAnnotation>(new SerializationTypeNameAnnotation
                {
                    TypeName = typeName
                });
            }
        }
 public void TypeNameShouldComeFromSerializationTypeNameAnnotationForComplexValue()
 {
     var stna = new SerializationTypeNameAnnotation() {TypeName = "FromSTNA"};
     var value = new ODataComplexValue() {TypeName = "Model.Bla"};
     value.SetAnnotation(stna);
     this.typeNameOracle.GetValueTypeNameForWriting(value,
         new EdmComplexTypeReference(new EdmComplexType("Model", "Bla"), true),
         new EdmComplexTypeReference(new EdmComplexType("Model", "Bla"), false),
         /* isOpenProperty*/ false).Should().Be("FromSTNA");
 }
        public void ValueWithTypeNameAnnotationShouldReturnTypeNameFromAnnotation()
        {
            var complexValue = new ODataComplexValue() { TypeName = ComplexTypeName };
            complexValue.SetAnnotation(new SerializationTypeNameAnnotation { TypeName = "TypeNameFromSTNA" });

            this.testSubject.GetValueTypeNameForWriting(
                complexValue,
                complexTypeReference,
                complexTypeReference,
                /*isOpen*/ false)
                .Should().Be("TypeNameFromSTNA");
        }
        public void CollectionValueSerializationTypeNameAnnotationTest()
        {
            #region test cases

            var testCases = new[]
            {
                new
                {
                    TypeName = (string)null,
                    SerializationTypeNameAnnotation = (SerializationTypeNameAnnotation)null,
                    XmlTypeName = MissingTypeNameSentinelTextAtom,
                    JsonTypeName = MissingTypeNameSentinelTextJson,
                    JsonLightTypeName = MissingTypeNameSentinelTextJson,
                    ExpectedExceptionInJsonLight = (object)ODataExpectedExceptions.ODataException("WriterValidationUtils_MissingTypeNameWithMetadata"),
                    ExpectedExceptionInAtom = new object(),
                    ExpectedExceptionInJsonLightForResponse = (object)ODataExpectedExceptions.ODataException("ODataContextUriBuilder_TypeNameMissingForProperty"),
                    ExpectedExceptionInAtomForResponse = (object)ODataExpectedExceptions.ODataException("ODataContextUriBuilder_TypeNameMissingForProperty"),
                },
                new
                {
                    TypeName = EntityModelUtils.GetCollectionTypeName("Edm.Int32"),
                    SerializationTypeNameAnnotation = (SerializationTypeNameAnnotation)null,
                    XmlTypeName = "<typeName>" + EntityModelUtils.GetCollectionTypeName("Edm.Int32") + "</typeName>",
                    JsonTypeName = "\"type\":\"" + EntityModelUtils.GetCollectionTypeName("Edm.Int32") + "\"",
                    JsonLightTypeName = MissingTypeNameSentinelTextJson,
                    ExpectedExceptionInJsonLight = new object(),
                    ExpectedExceptionInAtom = new object(),
                    ExpectedExceptionInJsonLightForResponse = new object(),
                    ExpectedExceptionInAtomForResponse = new object(),
                },
                new
                {
                    TypeName = EntityModelUtils.GetCollectionTypeName("Edm.Int32"),
                    SerializationTypeNameAnnotation = new SerializationTypeNameAnnotation() { TypeName = null },
                    XmlTypeName = MissingTypeNameSentinelTextAtom,
                    JsonTypeName = MissingTypeNameSentinelTextJson,
                    JsonLightTypeName = MissingTypeNameSentinelTextJson,
                    ExpectedExceptionInJsonLight = new object(),
                    ExpectedExceptionInAtom = new object(),
                    ExpectedExceptionInJsonLightForResponse = new object(),
                    ExpectedExceptionInAtomForResponse = new object(),
                },
                new
                {
                    TypeName = (string)null,
                    SerializationTypeNameAnnotation = new SerializationTypeNameAnnotation() { TypeName = EntityModelUtils.GetCollectionTypeName("Edm.String") },
                    XmlTypeName = "<typeName>" + EntityModelUtils.GetCollectionTypeName("Edm.String") + "</typeName>",
                    JsonTypeName = "\"type\":\"" + EntityModelUtils.GetCollectionTypeName("Edm.String") + "\"",
                    JsonLightTypeName = "\"@odata.type\":\"#" + EntityModelUtils.GetCollectionTypeName("Edm.String") + "\"",
                    ExpectedExceptionInJsonLight = (object)ODataExpectedExceptions.ODataException("WriterValidationUtils_MissingTypeNameWithMetadata"),
                    ExpectedExceptionInAtom = new object(),
                    ExpectedExceptionInJsonLightForResponse = (object)ODataExpectedExceptions.ODataException("ODataJsonLightValueSerializer_MissingTypeNameOnCollection"),
                    ExpectedExceptionInAtomForResponse = new object(),
                },
                new
                {
                    TypeName = (string)null,
                    SerializationTypeNameAnnotation = new SerializationTypeNameAnnotation() { TypeName = string.Empty },
                    XmlTypeName = "<typeName></typeName>",
                    JsonTypeName = "\"type\":\"\"",
                    JsonLightTypeName = "\"@odata.type\":\"\"",
                    ExpectedExceptionInJsonLight = (object)ODataExpectedExceptions.ODataException("WriterValidationUtils_MissingTypeNameWithMetadata"),
                    ExpectedExceptionInAtom = new object(),
                    ExpectedExceptionInJsonLightForResponse = (object)ODataExpectedExceptions.ODataException("ODataContextUriBuilder_TypeNameMissingForProperty"),
                    ExpectedExceptionInAtomForResponse = (object)ODataExpectedExceptions.ODataException("ODataContextUriBuilder_TypeNameMissingForProperty"),
                },
                new
                {
                    TypeName = (string)null,
                    SerializationTypeNameAnnotation = new SerializationTypeNameAnnotation() { TypeName = "NonCollectionTypeName" },
                    XmlTypeName = "<typeName>NonCollectionTypeName</typeName>",
                    JsonTypeName = "\"type\":\"NonCollectionTypeName\"",
                    JsonLightTypeName = "\"@odata.type\":\"#NonCollectionTypeName\"",
                    ExpectedExceptionInJsonLight = (object)ODataExpectedExceptions.ODataException("WriterValidationUtils_MissingTypeNameWithMetadata"),
                    ExpectedExceptionInAtom = new object(),
                    ExpectedExceptionInJsonLightForResponse = (object)ODataExpectedExceptions.ODataException("ODataJsonLightValueSerializer_MissingTypeNameOnCollection"),
                    ExpectedExceptionInAtomForResponse = new object(),
                },
                new
                {
                    TypeName = EntityModelUtils.GetCollectionTypeName("Edm.Int32"),
                    SerializationTypeNameAnnotation = new SerializationTypeNameAnnotation() { TypeName = EntityModelUtils.GetCollectionTypeName("Edm.String") },
                    XmlTypeName = "<typeName>" + EntityModelUtils.GetCollectionTypeName("Edm.String") + "</typeName>",
                    JsonTypeName = "\"type\":\"" + EntityModelUtils.GetCollectionTypeName("Edm.String") + "\"",
                    JsonLightTypeName = "\"@odata.type\":\"#" + EntityModelUtils.GetCollectionTypeName("Edm.String") + "\"",
                    ExpectedExceptionInJsonLight = new object(),
                    ExpectedExceptionInAtom = new object(),
                    ExpectedExceptionInJsonLightForResponse = new object(),
                    ExpectedExceptionInAtomForResponse = new object(),
                },
            };
            #endregion test cases

            var testDescriptors = testCases.Select(tc =>
            {
                EdmModel model = new EdmModel();

                var owningEntityType = new EdmEntityType("TestNS", "OwningEntityType");
                owningEntityType.AddStructuralProperty("PropertyName", EdmCoreModel.GetCollection(EdmCoreModel.Instance.GetInt32(isNullable: false)));
                model.AddElement(owningEntityType);

                var container = new EdmEntityContainer("TestNS", "TestContainer");
                model.AddElement(container);

                ODataComplexValue complexValue = new ODataComplexValue();
                complexValue.TypeName = tc.TypeName;
                complexValue.Properties = new[] { new ODataProperty() { Name = "TestProperty", Value = "TestValue" } };
                if (tc.SerializationTypeNameAnnotation != null)
                {
                    complexValue.SetAnnotation(tc.SerializationTypeNameAnnotation);
                }

                ODataCollectionValue collection = new ODataCollectionValue();
                collection.TypeName = tc.TypeName;
                if (tc.SerializationTypeNameAnnotation != null)
                {
                    collection.SetAnnotation(tc.SerializationTypeNameAnnotation);
                }

                return new PayloadWriterTestDescriptor<ODataProperty>(
                    this.Settings,
                    new ODataProperty { Name = "PropertyName", Value = collection },
                    (testConfiguration) =>
                    {
                        if (testConfiguration.Format == ODataFormat.Atom)
                        {
                            if (tc.ExpectedExceptionInAtom is Exception)
                            {
                                return new WriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                                {
                                    ExpectedException = (Exception)tc.ExpectedExceptionInAtom
                                };
                            }

                            var exception = testConfiguration.IsRequest ? tc.ExpectedExceptionInAtom : tc.ExpectedExceptionInAtomForResponse;
                            if (exception is ExpectedException)
                            {
                                return new WriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                                {
                                    ExpectedException2 = (ExpectedException)exception
                                };
                            }

                            return new AtomWriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                            {
                                FragmentExtractor = (result) =>
                                {
                                    string typeName = (string)result.Attribute(TestAtomConstants.ODataMetadataXNamespace + TestAtomConstants.AtomTypeAttributeName);
                                    return typeName == null ? MissingTypeNameSentinelXElement : new XElement("typeName", typeName);
                                },
                                Xml = tc.XmlTypeName
                            };
                        }

                        if (testConfiguration.Format == ODataFormat.Json)
                        {
                            if (testConfiguration.Format == ODataFormat.Json)
                            {
                                if (tc.ExpectedExceptionInJsonLight is Exception)
                                {
                                    return new WriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                                    {
                                        ExpectedException = (Exception)tc.ExpectedExceptionInJsonLight
                                    };
                                }

                                var exception = testConfiguration.IsRequest ? tc.ExpectedExceptionInJsonLight : tc.ExpectedExceptionInJsonLightForResponse;

                                if (exception is ExpectedException)
                                {
                                    return new WriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                                    {
                                        ExpectedException2 = (ExpectedException)exception
                                    };
                                }
                            }

                            return new JsonWriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                            {
                                FragmentExtractor = (result) =>
                                {
                                    var topLevelJsonObject = JsonLightWriterUtils.TrimWhitespace(result).Object();
                                    JsonProperty typeProperty = null;
                                    if (topLevelJsonObject != null)
                                    {
                                        typeProperty = topLevelJsonObject.Property(JsonLightConstants.ODataTypeAnnotationName);
                                    }

                                    return typeProperty == null ? MissingTypeNameSentinelJsonProperty : typeProperty.RemoveAllAnnotations(true);
                                },
                                Json = tc.JsonLightTypeName
                            };
                        }

                        throw new NotSupportedException("Format " + testConfiguration.Format.GetType().Name + " is not supported.");
                    })
                    {
                        Model = model,
                        PayloadEdmElementContainer = owningEntityType
                    };
            });

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors,
                this.WriterTestConfigurationProvider.ExplicitFormatConfigurationsWithIndent,
                (testDescriptor, testConfig) =>
                {
                    testConfig = testConfig.Clone();
                    testConfig.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri);
                    testDescriptor.RunTopLevelPropertyPayload(testConfig, baselineLogger: this.Logger);
                });
        }
        public void ComplexValueSerializationTypeNameAnnotationTest()
        {
            // TODO: Move this string to resources and localize it
            const string ODataJsonLightValueSerializer_MissingTypeNameOnComplex = "A type name was not provided for an instance of ODataComplexValue.";

            var testCases = new[]
            {
                new
                {
                    TypeName = (string)null,
                    SerializationTypeNameAnnotation = (SerializationTypeNameAnnotation)null,
                    XmlTypeName = MissingTypeNameSentinelTextAtom,
                    JsonLightTypeName = (string)null,
                    ExpectedExceptionInJsonLight = (object)ODataExpectedExceptions.ODataException("ODataJsonLightValueSerializer_MissingTypeNameOnComplex"),
                    ExpectedExceptionInAtom = (object) null,
                    ExpectedExceptionInJsonLightForResponse = (object)ODataExpectedExceptions.ODataException("ODataContextUriBuilder_TypeNameMissingForProperty"),
                    ExpectedExceptionInAtomForResponse = (object)ODataExpectedExceptions.ODataException("ODataContextUriBuilder_TypeNameMissingForProperty")
                },
                new
                {
                    TypeName = "TestNS.MyType",
                    SerializationTypeNameAnnotation = (SerializationTypeNameAnnotation)null,
                    XmlTypeName = "<typeName>TestNS.MyType</typeName>",
                    JsonLightTypeName = MissingTypeNameSentinelTextJson,
                    ExpectedExceptionInJsonLight = (object) null,
                    ExpectedExceptionInAtom = (object) null,
                    ExpectedExceptionInJsonLightForResponse = (object) null,
                    ExpectedExceptionInAtomForResponse = (object) null,
                },
                new
                {
                    TypeName = "TestNS.MyType",
                    SerializationTypeNameAnnotation = new SerializationTypeNameAnnotation() { TypeName = null },
                    XmlTypeName = MissingTypeNameSentinelTextAtom,
                    JsonLightTypeName = MissingTypeNameSentinelTextJson,
                    ExpectedExceptionInJsonLight = (object) null,
                    ExpectedExceptionInAtom = (object) null,
                    ExpectedExceptionInJsonLightForResponse = (object) null,
                    ExpectedExceptionInAtomForResponse = (object) null,
                },
                new
                {
                    TypeName = (string)null,
                    SerializationTypeNameAnnotation = new SerializationTypeNameAnnotation() { TypeName = "DifferentType" },
                    XmlTypeName = "<typeName>DifferentType</typeName>",
                    JsonLightTypeName = (string) null,
                    ExpectedExceptionInJsonLight = (object) new ODataException(ODataJsonLightValueSerializer_MissingTypeNameOnComplex),
                    ExpectedExceptionInAtom = (object) null,
                    ExpectedExceptionInJsonLightForResponse = (object) null,
                    ExpectedExceptionInAtomForResponse = (object) null,
                },
                new
                {
                    TypeName = (string)null,
                    SerializationTypeNameAnnotation = new SerializationTypeNameAnnotation() { TypeName = string.Empty },
                    XmlTypeName = "<typeName></typeName>",
                    JsonLightTypeName = (string) null,
                    ExpectedExceptionInJsonLight = (object)ODataExpectedExceptions.ODataException("ODataJsonLightValueSerializer_MissingTypeNameOnComplex"),
                    ExpectedExceptionInAtom = (object) null,
                    ExpectedExceptionInJsonLightForResponse = (object)ODataExpectedExceptions.ODataException("ODataContextUriBuilder_TypeNameMissingForProperty"),
                    ExpectedExceptionInAtomForResponse = (object)ODataExpectedExceptions.ODataException("ODataContextUriBuilder_TypeNameMissingForProperty"),
                },
                new
                {
                    TypeName = "TestNS.MyType",
                    SerializationTypeNameAnnotation = new SerializationTypeNameAnnotation() { TypeName = "DifferentType" },
                    XmlTypeName = "<typeName>DifferentType</typeName>",
                    JsonLightTypeName = "\"" + JsonLightConstants.ODataPropertyAnnotationSeparator + JsonLightConstants.ODataTypeAnnotationName + "\":\"DifferentType\"",
                    ExpectedExceptionInJsonLight = (object) null,
                    ExpectedExceptionInAtom = (object) null,
                    ExpectedExceptionInJsonLightForResponse = (object) null,
                    ExpectedExceptionInAtomForResponse = (object) null,
                },
            };

            var testDescriptors = testCases.Select(tc =>
            {
                EdmModel model = new EdmModel();

                var complexType = new EdmComplexType("TestNS", "MyType");
                complexType.AddStructuralProperty("TestProperty", EdmCoreModel.Instance.GetString(isNullable: true));
                model.AddElement(complexType);

                var owningEntityType = new EdmEntityType("TestNS", "OwningEntityType");
                owningEntityType.AddStructuralProperty("PropertyName", new EdmComplexTypeReference(complexType, isNullable: true));
                model.AddElement(owningEntityType);

                var container = new EdmEntityContainer("TestNS", "TestContainer");
                model.AddElement(container);

                ODataComplexValue complexValue = new ODataComplexValue();
                complexValue.TypeName = tc.TypeName;
                complexValue.Properties = new[] { new ODataProperty() { Name = "TestProperty", Value = "TestValue"} };
                if (tc.SerializationTypeNameAnnotation != null)
                {
                    complexValue.SetAnnotation(tc.SerializationTypeNameAnnotation);
                }

                return new PayloadWriterTestDescriptor<ODataProperty>(
                    this.Settings,
                    new ODataProperty { Name = "PropertyName", Value = complexValue },
                    (testConfiguration) =>
                    {
                        if (testConfiguration.Format == ODataFormat.Atom)
                        {
                            if (tc.ExpectedExceptionInAtom is Exception)
                            {
                                return new WriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                                {
                                    ExpectedException = (Exception)tc.ExpectedExceptionInAtom
                                };
                            }

                            var exception = testConfiguration.IsRequest ? tc.ExpectedExceptionInAtom : tc.ExpectedExceptionInAtomForResponse;
                            if (exception is ExpectedException)
                            {
                                return new WriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                                {
                                    ExpectedException2 = (ExpectedException)exception
                                };
                            }

                            return new AtomWriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                            {
                                FragmentExtractor = (result) =>
                                {
                                    string typeName = (string)result.Attribute(TestAtomConstants.ODataMetadataXNamespace + TestAtomConstants.AtomTypeAttributeName);
                                    return typeName == null ? MissingTypeNameSentinelXElement : new XElement("typeName", typeName);
                                },
                                Xml = tc.XmlTypeName
                            };
                        }
                        else if (testConfiguration.Format == ODataFormat.Json)
                        {
                            if (tc.ExpectedExceptionInJsonLight is Exception)
                            {
                                return new WriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                                {
                                    ExpectedException = (Exception)tc.ExpectedExceptionInJsonLight
                                };
                            }

                            var exception = testConfiguration.IsRequest ? tc.ExpectedExceptionInJsonLight : tc.ExpectedExceptionInJsonLightForResponse;
                            if (exception is ExpectedException)
                            {
                                return new WriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                                {
                                    ExpectedException2 = (ExpectedException)exception
                                };
                            }

                            return new JsonWriterTestExpectedResults(this.Settings.ExpectedResultSettings)
                            {
                                FragmentExtractor = (result) =>
                                {
                                    var complexObject = JsonLightWriterUtils.TrimWhitespace(result).Object();
                                    JsonProperty typeProperty = null;
                                    if (complexObject != null)
                                    {
                                        typeProperty = complexObject.Property(JsonLightConstants.ODataTypeAnnotationName);
                                    }

                                    return typeProperty == null ? MissingTypeNameSentinelJsonProperty : typeProperty.RemoveAllAnnotations(true);
                                },
                                Json = tc.JsonLightTypeName
                            };
                        }
                        else
                        {
                            throw new NotSupportedException("Format " + testConfiguration.Format.GetType().Name + " is not supported.");
                        }
                    })
                {
                    Model = model,
                    PayloadEdmElementContainer = owningEntityType
                };
            });

            this.CombinatorialEngineProvider.RunCombinations(
                testDescriptors,
                this.WriterTestConfigurationProvider.ExplicitFormatConfigurationsWithIndent,
                (testDescriptor, testConfiguration) =>
                {
                    testConfiguration = testConfiguration.Clone();
                    testConfiguration.MessageWriterSettings.SetServiceDocumentUri(ServiceDocumentUri);
                    testDescriptor.RunTopLevelPropertyPayload(testConfiguration, baselineLogger: this.Logger);
                });
        }
 public void BuildPropertyContextUriForComplexPropertyValueWithNonNullAnnotation()
 {
     ODataComplexValue value = new ODataComplexValue { TypeName = "FQNS.FromObject" };
     value.SetAnnotation(new SerializationTypeNameAnnotation { TypeName = "FQNS.FromAnnotation" });
     var contextUri = this.CreatePropertyContextUri(value);
     contextUri.OriginalString.Should().Be(BuildExpectedContextUri("#FQNS.FromAnnotation"));
 }
        internal static IEdmValue CreateStructuredEdmValue(ODataComplexValue complexValue, IEdmComplexTypeReference complexType)
        {
            if (complexType != null)
            {
                object typeAnnotation = ReflectionUtils.CreateInstance(
                    odataTypeAnnotationType,
                    new Type[] { typeof(IEdmComplexTypeReference) },
                    complexType);
                complexValue.SetAnnotation(typeAnnotation);
            }

            return (IEdmValue)ReflectionUtils.CreateInstance(
                odataEdmStructuredValueType,
                new Type[] { typeof(ODataComplexValue) },
                complexValue);
        }
        /// <summary>
        /// Creates and returns an ODataComplexValue from the given value.
        /// </summary>
        /// <param name="complexType">The value type.</param>
        /// <param name="value">The complex value.</param>
        /// <param name="propertyName">If the value is a property, then it represents the name of the property. Can be null, for non-property.</param>
        /// <param name="isCollectionItem">True, if the value is an item in a collection, false otherwise.</param>
        /// <param name="visitedComplexTypeObjects">Set of instances of complex types encountered in the hierarchy. Used to detect cycles.</param>
        /// <returns>An ODataComplexValue representing the given value.</returns>
        internal ODataComplexValue CreateODataComplexValue(Type complexType, object value, string propertyName, bool isCollectionItem, HashSet<object> visitedComplexTypeObjects)
        {
            Debug.Assert(complexType != null, "complexType != null");
            Debug.Assert(value != null || !isCollectionItem, "Collection items must not be null");

            ClientEdmModel model = this.requestInfo.Model;
            ClientTypeAnnotation complexTypeAnnotation = model.GetClientTypeAnnotation(complexType);
            Debug.Assert(complexTypeAnnotation != null, "complexTypeAnnotation != null");
            Debug.Assert(!complexTypeAnnotation.IsEntityType, "Unexpected entity");

            // Handle null values for complex types by putting m:null="true"
            if (value == null)
            {
                Debug.Assert(!isCollectionItem, "Null collection items are not supported. Should have already been checked.");
                return null;
            }

            if (visitedComplexTypeObjects == null)
            {
                visitedComplexTypeObjects = new HashSet<object>(ReferenceEqualityComparer<object>.Instance);
            }
            else if (visitedComplexTypeObjects.Contains(value))
            {
                if (propertyName != null)
                {
                    throw Error.InvalidOperation(Strings.Serializer_LoopsNotAllowedInComplexTypes(propertyName));
                }
                else
                {
                    Debug.Assert(complexTypeAnnotation.ElementTypeName != null, "complexTypeAnnotation.ElementTypeName != null");
                    throw Error.InvalidOperation(Strings.Serializer_LoopsNotAllowedInNonPropertyComplexTypes(complexTypeAnnotation.ElementTypeName));
                }
            }

            visitedComplexTypeObjects.Add(value);
            ODataComplexValue odataComplexValue = new ODataComplexValue();

            // When TypeName is set, it causes validation to occur when ODataLib writes out the collection. Part of the validation ensures that all items
            // in the collection are exactly the same type, no derived types are allowed. In the released WCF Data Services 5.0 implementation, we don't set
            // TypeName here, so that validation does not occur, therefore we will set this value only for JSON Light, so we don't break existing code.
            if (!this.requestInfo.Format.UsingAtom)
            {
                odataComplexValue.TypeName = complexTypeAnnotation.ElementTypeName;
            }

            string serverTypeName = this.requestInfo.GetServerTypeName(complexTypeAnnotation);
            odataComplexValue.SetAnnotation(new SerializationTypeNameAnnotation { TypeName = serverTypeName });
        
            odataComplexValue.Properties = this.PopulateProperties(value, serverTypeName, complexTypeAnnotation.PropertiesToSerialize(), visitedComplexTypeObjects);

            visitedComplexTypeObjects.Remove(value);
            return odataComplexValue;
        }