internal string GetEntryTypeNameForWriting(ODataEntry entry)
        {
            Debug.Assert(entry != null, "entry != null");

            SerializationTypeNameAnnotation typeNameAnnotation = entry.GetAnnotation <SerializationTypeNameAnnotation>();

            if (typeNameAnnotation != null)
            {
                return(typeNameAnnotation.TypeName);
            }

            return(entry.TypeName);
        }
        internal string GetValueTypeNameForWriting(
            object value,
            IEdmTypeReference typeReferenceFromValue,
            SerializationTypeNameAnnotation typeNameAnnotation,
            CollectionWithoutExpectedTypeValidator collectionValidator,
            out string collectionItemTypeName)
        {
            Debug.Assert(value != null, "value != null");

            collectionItemTypeName = null;

            // if no type name is specified we will use the type name inferred from metadata
            string typeName = GetTypeNameFromValue(value);

            if (typeName == null && typeReferenceFromValue != null)
            {
                typeName = typeReferenceFromValue.ODataFullName();
            }

            if (typeName != null)
            {
                // If the type is the same as the one specified by the parent collection, omit the type name, since it's not needed.
                if (collectionValidator != null && string.CompareOrdinal(collectionValidator.ItemTypeNameFromCollection, typeName) == 0)
                {
                    typeName = null;
                }

                // If value is a collection value, get the item type name.
                if (typeName != null && value is ODataCollectionValue)
                {
                    collectionItemTypeName = ValidationUtils.ValidateCollectionTypeName(typeName);
                }
            }

            if (typeNameAnnotation != null)
            {
                // If the value of TypeName is null, we'll flow it through here, thereby instructing the caller to write no type name.
                typeName = typeNameAnnotation.TypeName;
            }

            return(typeName);
        }
        internal string GetValueTypeNameForWriting(
            object value, 
            IEdmTypeReference typeReferenceFromValue, 
            SerializationTypeNameAnnotation typeNameAnnotation, 
            CollectionWithoutExpectedTypeValidator collectionValidator,
            out string collectionItemTypeName)
        {
            Debug.Assert(value != null, "value != null");

            collectionItemTypeName = null;

            // if no type name is specified we will use the type name inferred from metadata
            string typeName = GetTypeNameFromValue(value);
            if (typeName == null && typeReferenceFromValue != null)
            {
                typeName = typeReferenceFromValue.ODataFullName();
            }

            if (typeName != null)
            {
                // If the type is the same as the one specified by the parent collection, omit the type name, since it's not needed.
                if (collectionValidator != null && string.CompareOrdinal(collectionValidator.ItemTypeNameFromCollection, typeName) == 0)
                {
                    typeName = null;
                }

                // If value is a collection value, get the item type name.
                if (typeName != null && value is ODataCollectionValue)
                {
                    collectionItemTypeName = ValidationUtils.ValidateCollectionTypeName(typeName);
                }
            }

            if (typeNameAnnotation != null)
            {
                // If the value of TypeName is null, we'll flow it through here, thereby instructing the caller to write no type name.
                typeName = typeNameAnnotation.TypeName;
            }

            return typeName;
        }
        /// <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="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="messageReaderSettings">The message reader settings 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="serializationTypeNameAnnotation">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>
        internal static IEdmTypeReference ResolvePayloadTypeNameAndComputeTargetType(
            EdmTypeKind expectedTypeKind,
            IEdmType defaultPrimitivePayloadType,
            IEdmTypeReference expectedTypeReference,
            string payloadTypeName,
            IEdmModel model,
            ODataMessageReaderSettings messageReaderSettings,
            Func<EdmTypeKind> typeKindFromPayloadFunc,
            out EdmTypeKind targetTypeKind,
            out SerializationTypeNameAnnotation serializationTypeNameAnnotation)
        {
            Debug.Assert(typeKindFromPayloadFunc != null, "typeKindFromPayloadFunc != null");

            serializationTypeNameAnnotation = null;

            // What is the right behavior if both expected and actual types are specified for complex value?
            //             We decided that they have to match exactly.

            // Resolve the type name and get the payload type kind; that is the type kind of the payload
            // type if available or the expected type kind if no payload type could be resolved. Since
            // we always detect primitive and collection types the expected type for unrecognized payload
            // types is EdmTypeKind.Complex.
            EdmTypeKind payloadTypeKind;
            IEdmType payloadType = ResolvePayloadTypeName(
                model,
                expectedTypeReference,
                payloadTypeName,
                EdmTypeKind.Complex,
                messageReaderSettings.ReaderBehavior,
                out payloadTypeKind);

            // Compute the target type kind based on the expected type, the payload type kind
            // and a function to detect the target type kind from the shape of the payload.
            targetTypeKind = ComputeTargetTypeKind(
                expectedTypeReference,
                /*forEntityValue*/ expectedTypeKind == EdmTypeKind.Entity,
                payloadTypeName,
                payloadTypeKind,
                messageReaderSettings,
                typeKindFromPayloadFunc);

            // Resolve potential conflicts between payload and expected types and apply all the various behavior changing flags from settings
            IEdmTypeReference targetTypeReference;
            if (targetTypeKind == EdmTypeKind.Primitive)
            {
                targetTypeReference = ReaderValidationUtils.ResolveAndValidatePrimitiveTargetType(
                    expectedTypeReference,
                    payloadTypeKind,
                    payloadType,
                    payloadTypeName,
                    defaultPrimitivePayloadType,
                    model,
                    messageReaderSettings);
            }
            else
            {
                targetTypeReference = ReaderValidationUtils.ResolveAndValidateNonPrimitiveTargetType(
                    targetTypeKind,
                    expectedTypeReference,
                    payloadTypeKind,
                    payloadType,
                    payloadTypeName,
                    model,
                    messageReaderSettings);

                if (targetTypeReference != null)
                {
                    serializationTypeNameAnnotation = CreateSerializationTypeNameAnnotation(payloadTypeName, targetTypeReference);
                }
            }

            if (expectedTypeKind != EdmTypeKind.None && targetTypeReference != null)
            {
                ValidationUtils.ValidateTypeKind(targetTypeKind, expectedTypeKind, payloadTypeName);
            }

            return targetTypeReference;
        }
 public void TypeNameShouldComeFromSerializationTypeNameAnnotationForCollectionValue()
 {
     var stna = new SerializationTypeNameAnnotation() {TypeName = "FromSTNA"};
     var value = new ODataCollectionValue() {TypeName = "Collection(Edm.String)"};
     value.SetAnnotation(stna);
     this.typeNameOracle.GetValueTypeNameForWriting(value,
         EdmCoreModel.GetCollection(EdmCoreModel.Instance.GetString(true)),
         EdmCoreModel.GetCollection(EdmCoreModel.Instance.GetString(false)),
         /* isOpenProperty*/ false).Should().Be("FromSTNA");
 }
 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 TypeNameShouldComeFromSerializationTypeNameAnnotationForPrimitiveValue()
 {
     var stna = new SerializationTypeNameAnnotation() {TypeName = "FromSTNA"};
     var value = new ODataPrimitiveValue(42);
     value.SetAnnotation(stna);
     this.typeNameOracle.GetValueTypeNameForWriting(value,
         EdmCoreModel.Instance.GetInt32(true),
         EdmCoreModel.Instance.GetInt32(false),
         /* isOpenProperty*/ false).Should().Be("FromSTNA");
 }